关于 getsockname、getpeername和gethostname、gethostbyname

一、gethostname,gethostbyname的用法

这两个函数可以用来获取主机的信息。 gethostname:获取主机的名字 gethostbyname:通过名字获取其他的信息(比如ip)

1.gethostname: man手册里面的解释(部分):

       #include <unistd.h>
       int gethostname(char *name, size_t len);
       int sethostname(const char *name, size_t len);
DESCRIPTION
       These  system calls are used to access or to change the hostname of the
       current processor.
RETURN VALUE
       On  success,  zero is returned.  On error, -1 is returned, and errno is
       set appropriately.

2.gethostbyname:

       #include <netdb.h>
       extern int h_errno;
       struct hostent *gethostbyname(const char *name);

可以看到获取的内容保存在一个指针里面。下面我们来看这个指针指向的内容:        The hostent structure is defined in <netdb.h> as follows:            struct hostent {                char  *h_name;            /* official name of host */                char **h_aliases;         /* alias list */                int    h_addrtype;        /* host address type */                int    h_length;          /* length of address */                char **h_addr_list;       /* list of addresses */            }            #define h_addr h_addr_list[0] /* for backward compatibility */        The members of the hostent structure are:        h_name The official name of the host.        h_aliases               An array of alternative names for the host, terminated by a NULL               pointer.        h_addrtype               The type of address; always AF_INET or AF_INET6 at present.        h_length               The length of the address in bytes.        h_addr_list               An array of pointers to network addresses for the host (in  net‐               work byte order), terminated by a NULL pointer.        h_addr The first address in h_addr_list for backward compatibility.

然后是返回值: 失败返回空。否则返回值指向我们需要的信息的那个结构体。 RETURN VALUE        The  gethostbyname()  and  gethostbyaddr() functions return the hostent        structure or a NULL pointer if an error occurs.  On error, the  h_errno        variable  holds  an  error number.  When non-NULL, the return value may        point at static data, see the notes below.

实例:

#include<stdio.h>
#include<unistd.h>
#include<netdb.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
int main()
{
    
    printf("%s() +++ hello\n", __func__);
    char host[256] = {0};
    if(gethostname(host, sizeof(host)) < 0)
    {
        perror("gethostname");
        return -1;
    }    
    
    printf("host:%s\n", host);
    struct hostent *myhost = NULL;
    if(!(myhost = gethostbyname(host)))
    {
        perror("gethostbyname");
           return -2;
    }
    int i = 0;
    while(myhost && myhost->h_addr_list[i])
    {
        printf("ip%d:%s\n", i+1, inet_ntoa(*(struct in_addr*)myhost->h_addr_list[i]));
        i++;    
    }
    return 0;
}

运行:

xcy@xcy-virtual-machine:~/test/gethost$ ./a.out  main() +++ hello host:xcy-virtual-machine ip1:127.0.1.1

二、关于getsockname和getpeername

1.getsockname:获取一个套接字的名字。获取本地的地址和端口信息。 #include <sys/socket.h> int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 失败返回-1,成功返回0。addr是输入参数,addrlen是输入输出参数

2.getpeername:获取socket的对方的地址 #include <sys/socket.h> int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen); 失败返回-1,成功返回0。addr是输入参数,addrlen是输入输出参数

注意: 1)对于server来说: bind以后就可以调用getsockname来获取本地地址和端口了,只不过这样没啥意义,因为就是自己绑定的。 只有在accept以后(就是有连接之后才)才能用getpeername获取client的ip和端口。(client的ip和port也可以在accept函数的第二个参数中带出) 2)对于client来说: 创建socket并不会分配ip和端口。用getsockname获取出来的数据全是0. 在连接(connect)之后才可以用getsockname获取自己的ip和端口。也可以用getpeername获取服务器的。

3.如何使用:伪代码 客户端代码:

......
    if(connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
    {
        perror("connect");
        return -2;
    }
// 在连接以后才能获取
    struct sockaddr_in addr2;
    socklen_t len = sizeof(addr2); // 
    //if(getsockname(sockfd, (struct sockaddr*)&addr2, &len) < 0) // 这个是获取自己的ip和端口
    if(getpeername(sockfd, (struct sockaddr*)&addr2, &len) < 0)  // 这个是获取连接方的
    {
        perror("getsockname");
        return -3;
    }
printf("Get: port:%d, ip:%s\n", ntohs(addr2.sin_port), inet_ntoa(addr2.sin_addr));
......

服务端代码:

。。。// 前面有bind,listen等动作,这里只处理连接的
    while(1)
    {    
        int conn = accept(listenfd, (struct sockaddr*)&connaddr, &len);
        if(conn < 0)
        {
            perror("accept");
            return -4;
        }
          // 这里的connaddr就跟下面getpeername获取的一样
        char strip[64] = {0};
        char *ip = inet_ntoa(connaddr.sin_addr);
        strcpy(strip, ip);
        printf("new client connect,ip:%s, port:%d\n", strip,ntohs(connaddr.sin_port));
        struct sockaddr_in addr2;
        socklen_t len = sizeof(addr2);
    //    if(getsockname(conn, (struct sockaddr*)&addr2, &len) < 0) // 这个是获取自己的ip和端口
        if(getpeername(conn, (struct sockaddr*)&addr2, &len) < 0) // 这个是获取连接方的。这样其实跟accept参数带出来的数据是一样的
        {
            perror("getsockname");
            return -3;
        }
        printf("get: port:%d, ip:%s\n", ntohs(addr2.sin_port), inet_ntoa(addr2.sin_addr));        
        deal_connect(conn); // 用来处理连接的函数
    }
。。。。。。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏逸鹏说道

C# 温故而知新: 线程篇(二) 上

线程池和异步线程 目录: 1 什么是CLR线程池? 2 简单介绍下线程池各个优点的实现细节 3 线程池ThreadPool的常用方法介绍 4 简单理解下异步线程...

3199
来自专栏从零开始学自动化测试

pytest文档14-函数传参和fixture传参数request

为了提高代码的复用性,我们在写用例的时候,会用到函数,然后不同的用例去调用这个函数。 比如登录操作,大部分的用例都会先登录,那就需要把登录单独抽出来写个函数,其...

4492
来自专栏Python爬虫实战

Python指南:文件处理

哪种文件格式最适合用于存储整个数据集——二进制、文本还是XML?这严重依赖于具体的上下文。

1391
来自专栏技术之路

名称空间

using 声明和using 编译指令 using 声明将特定的名称添加到它所属的声明区域中。 using std::cout; 将cout添加到声明区中,声明...

1867
来自专栏前端小吉米

async/await 一种非常丝滑的异步语法

1883
来自专栏青青天空树

mfc学习之路--如何删除通过控件新增的变量

   刚刚学校mfc的人都会遇到这样一个问题(比如我),在照做书做一个mfc程序,给控件新增变量时变量类型错了,但是变量名对了,然后想要加个正确的时候提示"已经...

975
来自专栏余林丰

虚拟机类加载机制(2)——类加载器

《深入理解Java虚拟机》一书中将类的加载过程放到了类加载器前面一节,但在这里我想先讲“类加载器”。在上一篇类加载时机中我们用大量篇幅来讲解了类加载过程中的5个...

2156
来自专栏IT技术精选文摘

Shell入门指南

1553
来自专栏IT笔记

如何限制input输入类型

1.只能输入和粘贴汉字 <input onkeyup="value=value.replace(/1/g,'')" onbeforepaste="clipbo...

3927
来自专栏云计算教程系列

如何使用Grep

Grep是一个命令行实用程序,可以使用常见的正则表达式语法搜索和过滤文本。它无处不在,动词“to grep”已经成为“搜索”的同义词。它grep是一个有用的工具...

1203

扫码关注云+社区

领取腾讯云代金券