网络套接字--地址转换函数

sockaddr_in中的成员struct in_addr sin_addr表示32位的IP地址,但是我们通常采用的是利用点分十进制IDE字符串来表示IP地址,以下的函数可以在字符串表示和in_addr表示之间的转换。
字符串转in_addr的函数:
这里写图片描述
这里写图片描述
in_addr转字符串的函数
这里写图片描述
这里写图片描述

其中inet_ptoa和inet_ntop比较近可以转换为IPV6的in6_addr,因此函数接口是void *addrptr。
代码示例:

1 #include <stdio.h>
  2 #include <sys/socket.h>
  3 #include <netinet/in.h>
  4 #include <arpa/inet.h>
  5 
  6 int main()
  7 {
  8     struct sockaddr_in addr;
  9     inet_aton("127.0.0.1",&addr.sin_addr);
 10     uint32_t* ptr=(uint32_t* )(&addr.sin_addr);
 11     printf("addr: %x\n",*ptr);
 12     printf("add_str:%s\n",inet_ntoa(addr.sin_addr));
 13     return 0;
 14 }
 15          

运行的结果为:
这里写图片描述
关于inet_ntoa
inet_ntoa这个函数返回了一个char* ,很显然是这个函数自己在内部为我们申请了一块内存来保持ip的结果,那么是否需要调用者手动释放呢?
我们通过查找可以知道的是inet_ntoa函数将返回的结果放到了静态存储区。这个时候我们就不需要进行手动的释放了。
那么我们多次条用这个函数将会出现什么样的结果呢?

 1 #include <stdio.h>
  2 #include <netinet/in.h>
  3 #include <arpa/inet.h>                                                      
  4 
  5 
  6 int main()
  7 {
  8     struct sockaddr_in addr1;
  9     struct sockaddr_in addr2;
 10     addr1.sin_addr.s_addr=0;
 11     addr2.sin_addr.s_addr=0xffffffff;
 12     char *ptr1=inet_ntoa(addr1.sin_addr);
 13     char *ptr2=inet_ntoa(addr2.sin_addr);
 14     printf("ptr1: %s,ptr2: %s\n",ptr1,ptr2);
 15     return 0;
 16 }

结果如下:
这里写图片描述
因为inet_ntoa把结果放到了自己的静态存储区,这样我们在第二次条用的时候会覆盖掉上一次的结果。

  • 我们在多个线程调用的时候会不会出现这样的异常情况呢?

    • APUE明确的规定inet_ntoa不是线程安全函数。
    • 但是我们在centos7上进行测试,并没有出现问题,可能是内部实现了互斥锁;
    • 在多线程的环境下,我们推荐使用的是inet_ntop,这个函数由调用者提供一个缓冲区保存结果,可以有效的避免线程安全的问题;

    多线程调用inet_ntop代码如下:

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>


void* Func1(void* p)
{
    struct sockaddr_in* addr=(struct sockaddr_in*)p;
    while(1)
    {
    char buf[1024];
    inet_ntop(AF_INET,&(addr->sin_addr),&buf,(socklen_t)sizeof(buf));
    sleep(1);
    printf("addr1: %s\n",buf);
    }
    return NULL;
}

void* Func2(void* p)
{
    struct sockaddr_in* addr=(struct sockaddr_in*)p;
    while(1)
    {
    char buf[1024];
    inet_ntop(AF_INET,&(addr->sin_addr),&buf,(socklen_t)sizeof(buf));
    sleep(1);
    printf("addr2: %s\n",buf);
    }
    return NULL;
}


int main()
{
    pthread_t tid1=0;
    struct sockaddr_in addr1;
    struct sockaddr_in addr2;
    addr1.sin_addr.s_addr=0;
    addr2.sin_addr.s_addr=0xffffffff;
    pthread_create(&tid1,NULL,Func1,&addr1);
    pthread_t tid2=0;
    pthread_create(&tid2,NULL,Func2,&addr2);
    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    return 0;
}

运行结果:
这里写图片描述
我们看到的结果就是在使用的时候,这个inet_ntop在使用的时会比inet_ntoa好点,不会在多线程调用的时候出现异常的情况。

猜你喜欢

转载自blog.csdn.net/daboluo521/article/details/80531309