linux的套接字部分比较容易混乱,在这里稍微总结一下。
地址转换函数在地址的文本表达式和它们存放在套接字地址结构中的二进制值进行转换。
地址转换函数有四个:其中inet_addr 和 inet_ntoa适用于IPv4,inet_pton 和 inet_ntop同时适于用IPv4和IPv6。
套接字地址结构分为IPv4套接字地址结构sockaddr_in和IPv6套接字地址结构sockaddr_in6。其中IPv4的套接字地址结构如下。
IPv4套接字地址结构:(定义在
-->说明:POSIX规范只需要这个结构中的3个字段:sin_family、sin_addr和sin_port。对于符合POSIX的实现来说,定义额外的结构字段是可以接受的。几乎所有的实现都增加了sin_zero字段,所以所有的套接字地址结构大小都至少是16字节。
-->IPv4地址和TCP或UDP端口号在套接字地址结构中总是以网络字节序来存储,在使用这些字段时,必须要牢记这一点。
-->32位IPv4地址存在两种不同的访问方法。例如:如果serv第一位某个网际套接字地址结构,那么serv.sin_addr将按in_addr结构引用其中的32位IPv4地址,而serv.sin_addr.s_addr将按in_addr_t(通常是一个uint32_t)引用同一个32位Ipv4地址。在将它作为函数的参数时要注意使用正确的IPv4地址,因为编译器对传递结构和传递正数的处理是完全不同的。
-->sin_zero字段未曾使用,不过在填写这种套接字地址结构时,总是把该字段置为0(总是在填写前把整个结构置为0)
-->套接字地址结构仅在给定主机上使用:虽然结构中的某些字段(例如IP地址和端口号)用在不同主机之间的通信,但是结构本身并不在主机之间传递。
通用套接字地址结构:
-->当作为一个参数传递进任何套接字函数时,套接字地址结构总是以引用形式(也就是以指向该结构的指针)来传递。然而以这样的指针作为参数之一的任何套接字函数必须处理来自所有支持的任何协议族的套接字地址结构。在如何声明所传递指针的数据类型上存在一个问题,有了ANSI C后解决办法:void *。然而在ANSI C之前的解决办法是在
struct sockaddr{ uint8_t sa_len; sa_family_t sa_family; char sa_data[14];};于是套接字函数被定义为以指向某个通用套接字地址结构的一个指针作为其参数之一,例如bind函数的ANSI C函数原型:
int bind(int, struct sockaddr *, socklen_t); //一般是uint32_t
这就要求对这些函数的任何调用都必须要将指向特定于协议的套接字地址结构的指针进行强制类型转换,变成指向某个通用套接字地址类型的指针,如:
值–结果参数
当向一个套接字函数传递一个套接字地址结构时,该结构总是以引用形式来传递,也就是说传递的是一个指向该结构的一个指针。该结构的长度也作为一个参数来传递,但是其传递方式取决于该结构的传递方向:进程–>内核,内核–>进程
从进程到内核传递套接字地址结构的函数有3个:bind,connect,sendto。这些函数的一个参数是指向某个套接字地址结构的指针,另一个参数是该结构的整数大小,例如:
从内核到进程传递套接字地址结构的函数有4个:accept, recvfrom,getsockname和getpeername。这4个函数的其中两个参数是指向某个套接字地址结构的指针和指向表示该结构大小的整数的指针,如:
把套接字地址结构大小这个参数从一个整数改为指向某个整数变量的指针,其原因在于:当单数被调用时,结构大小是一个值,它告诉内核结构的大小,这样内核在写该结构时不至于越界;当函数返回时,结构大小又是一个结果,它告诉进程内核在该结构中究竟存储了多少信息。这种类型的参数成为值-结果参数。
网络字节序 <–> 主机字节序:有四个函数用于网络字节序和主机字节序之间的转换:
以下两个均返回网络字节序
以下两个均返回主机字节序
地址转换函数(两组):
inet_aton, inet_addr, inet_ntoa:这一组函数在点分十进制字符串(“206.168.112.96”)与它长度为32位的网络字节序二进制值间转换IPv4地址。原型如下:
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的结构体而不是指针。
inet_pton,inet_ntop这一组函数对IPv4和IPv6地址都适用。原型如下:
原文链接:http://www.cnblogs.com/uangyy/p/5456094.html