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好点,不会在多线程调用的时候出现异常的情况。