坚持每天学习,坚持写博客。
二月份加油
套接字地址结构
通用套接字数据结构
实际使用的套接字数据结构
结构sockaddr和结构sockaddr_in的关系
用户层和内核层交换过程
向内核传入数据的交互过程
内核传出数据的交互过程
套接字编程需要指定套接字的地址作为参数,不同的协议族有不同的地址结构定义方式。这些地址结构通常以sockaddr_开头,每一个协议族有一个唯一的后缀,例如对于以太网,其结构名称为sockaddr_in。
通用的套接字地址类型的定义如下,它可以在不同协议族之间进行强制转换。‘
上述结构中协议族成员变量sa_family的类型为sa_family_t,其实这个类型是unsigned short类型,因此成员变量sa_family的长度为16个字节。
在网络程序设计中所使用的函数中几乎所有的套接字函数都用这个结构作为参数,例如bind()函数的原型为:
但是使用结构struct sockaddr不方便进行设置,在以太网中,一般采结构struct sockaddr_in进行设置,这个结构的定义如下:
结构struct sockaddr_in的成员in_addr用于表示IP地址,这个结构的定义如下:
结构struct sockaddr和结构struct sockaddr_in是一个同样大小的结构,其对应关系参见图
struct sockaddr_in中的成员含义如下所述。
sin_len:无符号字符类型,表示结构struct sockaddr_in的长度,为16.
sin_family:无符号字符类型,通常设置为与socket()函数的domain一致,例如AF_INET。
sin_port:无符号short类型,表示端口号,网络字节序
sin_addr:struct in_addr类型,其成员s_addr为无符号32位数,每8位表示IP地址的一个段,网络字节序。
sin_zero[8]:char类型,保留。
由于结构struct sockaddr和结构struct sockaddr_in的大小是完全一致的,所以进行地址结构设置时,通常的方法是利用结构struct sockaddr_in进行设置,然后强制转换位结构struct sockaddr类型。因为这两个结构大小是完全一致的,所以进行这样的转换不会有副作用。
套接字参数中有部分参数是需要用户传入的,这些参数用来与Linux内核进行通信,例如指向地址结构的指针。通常是采用内存复制的方法进行。例如bind()函数需要传入地址结构struct sockaddr *my_addr和my_addr指向参数的长度。
向内核传入数据的函数有send()、bind()等,从内核得到数据的函数有accept()、recv()等。传入的过程如图所示,bind()函数向内核中传入的参数有套接字地址结构和结构的长度两个结构有关的参数。
参数addlen表示地址结构的长度,参数my_addr是指向地址结构的指针。调用函数bind()的时候,地址结构通过内存复制的方式将其中的内容分复制到内核,地址结构长度通过传值的方式传入内核,内核按照用户传入的地址结构长度来复制套接字地址结构的内容。
从内核向用户空间传递参数的过程则相反,传出的过程如图所示,通过地址结构的长度和套接字地址结构指针来进行地址结构参数的传出操作。通常是两个参数完成传出操作的功能,一个表示地址长度的参数,另一个表示套接字地址结构地址的指针。
传出过程与传入过程的参数不同的是,表示地址结构长度的参数在传入过程中是传值,而在传出过程中是通过传址完成的。内核按照用户传入的地址结构长度进行套接字地址结构数据的复制,将内核中的地址结构数据复制到用户传入的地址结构指针中。