标签:
linux的套接字部分比较容易混乱,在这里稍微总结一下。
地址转换函数在地址的文本表达式和它们存放在套接字地址结构中的二进制值进行转换。
地址转换函数有四个:其中inet_addr 和 inet_ntoa适用于IPv4,inet_pton 和 inet_ntop同时适于用IPv4和IPv6。
1 struct in_addr{ 2 in_addr_t s_addr; // 3 }; 4 5 struct sockaddr_in{ 6 uint8_t sin_len; 7 sa_family_t sin_family; //套接字地址结构的地址族 8 in_port_t sin_port //TCP或UDP端口,一般为uint16_t 9 struct in_addr sin_addr; //IPv4地址,一般为uint32_t 10 char sin_zero[8]; 11 };
说明:POSIX规范只需要这个结构中的3个字段:sin_family、sin_addr和sin_port。对于符合POSIX的实现来说,定义额外的结构字段是可以接受的。几乎所有的实现都增加了sin_zero字段,所以所有的套接字地址结构大小都至少是16字节。
1 struct sockaddr{ 2 uint8_t sa_len; 3 sa_family_t sa_family; 4 char sa_data[14]; 5 };
于是套接字函数被定义为以指向某个通用套接字地址结构的一个指针作为其参数之一,例如bind函数的ANSI C函数原型:
int bind(int, struct sockaddr *, socklen_t); //一般是uint32_t
这就要求对这些函数的任何调用都必须要将指向特定于协议的套接字地址结构的指针进行强制类型转换,变成指向某个通用套接字地址类型的指针,如:
struct sockaddr_in serv; bind(sockfd, (struct sockaddr *) &serv, sizeof(serv));
struct sockaddr_in serv; connect(sockdf, (SA *) &serv, sizof(serv));
struct sockaddr_un cli; socklen_t len; len = sizeof(cli); getpeername(unixfd, (SA *) &cli, &len);
#include <arpa/inet.h> int inet_aton(const char *strptr, struct in_addr *addrptr); //返回:若字符串有效则为1,否则为0 in_addr_t inet_addr(const char *strptr); //返回:若字符串有效则为32位二进制网络字节序的IPv4地址,否则为INADDR_NONE char *inet_ntoa(struct in_addr inaddr); //返回:指向一个点分十进制数串的指针
//还有一个名为inet_network的函数和inet_addr类似,但是其返回的是主机字节序
in_addr_t inet_network(const char *strptr);
inet_aton 和 inet_addr 两个函数都是将一个点分十进制字符串转换成一个32位的网络字节序二进制值。inet_aton函数,如果addrptr指针为空,那么该函数仍然对输入的字符串执行有效性检查,但是不存储任何结果。inet_addr函数存在一些问题:所有2^32个可能的二进制值都是有效的ip地址(0.0.0.0-255.255.255.255),但是当出错时函数返回INADDR_NONE常量(通常是一个32位均为1的值),这意味着点分十进制数串255.255.255.255不能由该函数处理,因为它的二进制用来指示该函数失败,inet_addr还存在一个潜在的问题:一些手册声明该函数出错时返回-1而不是INADDR_NONE,这样在对该函数的返回值和一个负常量进行比较时可能会发生问题。如今,inet_addr已经废弃,新的代码应该改用inet_ato函数,更好的解决方法是使用inet_pton函数。另外需要注意的是inet_ntoa函数的参数是in_addr的结构体而不是指针。
#include <arpa/inet.h> int inet_pton(int family, const char *strptr, void *addrptr); //返回:若成功则为1,若输入不是有效的表达格式则为0,若出错则为-1 const char *inet_ntop(int family, void *addrptr, char *strptr, size_t len); //返回:若成功则为指向结果的指针,若出错则为NULL
inet_pton(AF_INET),inet_aton, inet_addr 点分十进制数 -----------------------------------------------------> in_addr{} IPv4地址 <----------------------------------------------------- 32位二进制IPv4地址 inet_ntop(AF_INET),inet_ntoa
#include <stdio.h> #include <string.h> #include <arpa/inet.h> int main(int argc, char **argv) { const char *ip_str = "127.0.0.1"; char *ip_res; in_addr_t addr_t; struct in_addr addr; //1.str -> binary inet_aton(ip_str, &addr); printf("inet_aton::%x\n", addr); //1000007f addr_t = inet_addr(ip_str); printf("inet_addr::%x\n", addr_t); //1000007f inet_pton(AF_INET, ip_str, (void *)&addr); //1000007f printf("inet_pton::%x\n", addr); //2.binary -> str ip_res = inet_ntoa(addr); printf("inet_ntoa::%s\n", ip_res); //127.0.0.1 inet_ntop(AF_INET, &addr, ip_res, INET_ADDRSTRLEN); printf("inet_ntop::%s\n", ip_res); //127.0.0.1 return 0; } output: inet_aton::100007f inet_addr::100007f inet_pton::100007f inet_ntoa::127.0.0.1 inet_ntop::127.0.0.1
标签:
原文地址:http://www.cnblogs.com/uangyy/p/5456094.html