开发者社区> xcywt> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

关于 getsockname、getpeername和gethostname、gethostbyname

简介: 一、gethostname,gethostbyname的用法 这两个函数可以用来获取主机的信息。gethostname:获取主机的名字gethostbyname:通过名字获取其他的信息(比如ip) 1.
+关注继续查看

一、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); // 用来处理连接的函数
    }
。。。。。。

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
错误 C4996 ‘inet_ntoa‘: Use inet_ntop() or InetNtop() instead or define _WINS
错误 C4996 ‘inet_ntoa‘: Use inet_ntop() or InetNtop() instead or define _WINS
0 0
TCP/IP源码(21)——struct inet_socks
本文的copyleft归gfree.wind@gmail.com所有,使用GPL发布,可以自由拷贝,转载。但转载请保持文档的完整性,注明原作者及原链接,严禁用于任何商业用途。 作者:gfree.wind@gmail.com 博客:linuxfocus.blog.chinaunix.net     在前面的博文中,我画出了TCP/IP数据包发送的流程图。
875 0
setsockopt中参数之SO_REUSEADDR的意义(转)
1、一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。     SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。
620 0
1、setsockopt中参数之SO_REUSEADDR的意义
1、一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用。     SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的socket,才可以重复绑定使用。
476 0
socket inet_pton
inet_pton  Linux下这2个IP地址转换函数,可以在将IP地址在“点分十进制”和“整数”之间转换  而且,inet_pton和inet_ntop这2个函数能够处理ipv4和ipv6。算是比较新的函数了。
526 0
+关注
xcywt
C++ 机器人行业
文章
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载