IP地址转换函数

IPv4的socket网络编程中,sockaddr_in中的成员struct in_addr sin-addr 表示32位的IP地址,但是通常我们使用的是点分十进制的字符串表示IP地址,那么这两个如何转换呢?

#include<arpa/inet.h>

字符串转in_addr的函数:
int_addr_t addr_t inet_addr(const char *strptr);

int inet_aton(const char* strptr,struct in_addr *addrptr);

int inet_pton(int family,const char* strptr,void *addrptr);


in_addr转字符串的函数:
char *inet_ntoa(struct in_addr inaddr);

const char *inet_ntop(int famliy,const void*addrptr,char *strptr,size_t len);

我们在UDP中,初始化sockaddr_in时,调用了 int_addr_t inet_addr(const char* strptr),把我们的命令行参数中的IP地址转换成了 int_addr_t

这里写图片描述

inet_ntop() 和 inet_pton() 函数不仅可以把IPv4的地址转成字符串,而且还可以把IPv6的地址也转成。

char *inet_ntoa(struct in_addr inaddr);
inet_ntoa() 返回的是一个指针,那么我们可以想到,该函数肯定是在某个位置保存了我们的IP地址了。
那么我们在调用结束的时候,是否需要去释放该地址空间。
操作系统中说明,该函数存放的IP地址空间开辟在了静态区,那么该函数调用结束就不需要我们手动去释放了。

提到静态区,那是一个全局变量,共享的,我们必当想到的是 ——数据安全的问题。

我们看如下代码:

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

int main()
{
    struct sockaddr_in addr1;
    struct sockaddr_in addr2;
    addr1.sin_addr.s_addr = 0;
    addr2.sin_addr.s_addr = 0xffffffff;
    char *ptr1 = inet_ntoa(addr1.sin_addr);
    char *ptr2 = inet_ntoa(addr2.sin_addr);
    printf("ptr1:%s,ptr2:%s\n",ptr1,ptr2);

}

运行结果:
这里写图片描述

因为inet_ntoa把结果放到自己内部的一个静态储存区中,这样第二次调用的结果UI覆盖掉上一次的结果。

在多线程环境下,推荐使用inet_ntop(),这个函数由调用者提供一个缓冲区保存结果,可以规避线程安全问题。

但是目前centos7中可能加了互斥锁,所以并没有出现覆盖的情况。如一下测试:

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

#include<pthread.h>

void *rout1(void *p)
{
    struct sockaddr_in *addr = (struct sockaddr_in *)p;
    while(1)
    {
        char *ptr = inet_ntoa(addr->sin_addr);
        printf("addr1:%s\n",ptr);
    }
    return NULL;
}


void *rout2(void *p)
{
    struct sockaddr_in *addr = (struct sockaddr_in *)p;
    while(1)
    {
        char *ptr = inet_ntoa(addr->sin_addr);
        printf("addr2:%s\n",ptr);
    }
    return NULL;
}

int main()
{
    pthread_t tid1,tid2;

    struct sockaddr_in addr1;
    struct sockaddr_in  addr2;
    addr1.sin_addr.s_addr = 0;
    addr2.sin_addr.s_addr = 0xffffffff;

    pthread_create(&tid1,NULL,rout1,&addr1);

    pthread_create(&tid2,NULL,rout2,&addr2);


    pthread_join(tid1,NULL);
    pthread_join(tid2,NULL);
    return 0;
}

运行结果如下:
这里写图片描述
并没有出现覆盖的那种情况。
但是在APUE中,明确提出了inet_addr()函数不是线程安全的函数。
我们在多线程情况下,建议使用inet_ntop().

猜你喜欢

转载自blog.csdn.net/Shawei_/article/details/81479395