zoukankan      html  css  js  c++  java
  • 关于 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
    ", __func__);
        char host[256] = {0};
        if(gethostname(host, sizeof(host)) < 0)
        {
            perror("gethostname");
            return -1;
        }    
        
        printf("host:%s
    ", 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
    ", 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
    ", 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
    ", 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
    ", ntohs(addr2.sin_port), inet_ntoa(addr2.sin_addr));        
            deal_connect(conn); // 用来处理连接的函数
        }
    。。。。。。
  • 相关阅读:
    docker(六):Dockerfile详解
    docker(五):存储卷管理
    安装VCenter 6.7
    VMware Workstation 不可恢复错误:(vmui) VERIFY bora
    HP DL360 G7安装esxi 6.0
    zabbix 4.0故障归纳
    docker(四):容器虚拟化网络概述
    安装VCenter 6.7时报错“系统未安装通用C”
    zookeeper查看日志
    zabbix(一):zabbix 4.0安装
  • 原文地址:https://www.cnblogs.com/xcywt/p/8039660.html
Copyright © 2011-2022 走看看