APUE读书笔记-第16章-网络IPC: 套接字
16.1 引言
*进程能够通过套接字网络IPC接口和其他进程通信。通过该接口,其他进程运行位置是透明的,它们可以在同一台计算机上也可以在不同的计算机上。实际上,这正是套接字的目标之一:同样的接口既可以用于计算机间通信又可以用于计算机内通信
*16.2 套接字描述符
*要创建一个套接字,可以调用socket函数
int socket(int domain, int type, int protocol);
*套接字通信是双向的,可以采用函数shutdown来禁止套接字上的输入/输出
int shutdown(int sockfd, int how);
16.3 寻址
*确定一个目标通信进程使用进程标识的方式,进程的标识有两个部分:计算机的网络地址可以帮助标识计算机网络上想与之通信的计算机,而服务可以帮助标识计算机上的特定的进程
*如果处理器架构支持大端(big-endian)字节序,那么最大字节地址对应于数字最低有效字节(LSB)上;小端(little-endian)字节序则相反:数字最低字节对应于最小字节地址
*套接字可以自由地添加额外的成员并且定义sa_data成员的大小
*在Linux中,套接字地址结构定义如下:
struct sockaddr{
sa_family_tsa_family;
charsa_data[14];
}
*在FreeBSD中,套接字地址结构定义如下:
struct sockaddr{
unsigned charsa_len;
sa_family_tsa_family;
charsa_data[14];
}
*在IPv4因特网(AF_INET)中,套接字地址用结构sockaddr_in表示
*可以用bind函数将地址绑定到一个套接字
16.4 建立连接
*可以用connect建立一个连接
*服务器调用listen来宣告可以接受连接请求
*使用函数accept获得连接请求并建立连接。函数accept所返回的文件描述符是套接字描述符,该描述符连接到调用connect的客户端
16.5 数据传输
*三个函数用来发送数据,三个用来接收数据
*最简单的是send,它和write很像,但是可以指定标识来改变处理传输数据的方式
*函数sendto和send很类似。区别在于sendto允许在无连接的套接字上制定一个目标地址
*可以使用不止一个的选择来通过套接字发送数据。可以调用带有msghdr结构的sendmsg来指定多重缓冲区传输数据,这和writev很相像
*函数recv和read很像,但是允许指定选项来控制如何接收数据
*如果有兴趣定位发送者,可以使用recvfrom来得到数据发送者的源地址
*为了将接收到的数据送入多个缓冲区(类似于readv),或者想接收辅助数据,可以使用recvmsg
16.6 套接字选项
*套接字机制提供两个套接字选项接口来控制套接字行为。一个接口用来设置选项,另一个接口允许查询一个选项的状态。可以获取或设置三种选项:
(1)通用选项,工作在所有套接字类型上
(2)在套接字层次管理的选项,但是依赖于下层协议的支持
(3)特定于某协议的选项,为每个协议所独有
*可以采用setsockopt函数来设置套接字选项
*使用getsockopt函数来发现选项的当前值
int getsockopt(int sockfd, int level, int option, void *restrict val, socklen_t *resctrict lenp)
注意到参数lenp是一个指向整数的指针。在调用getsockopt之前,设置该整数为复制选项缓冲区的大小。如果实际的尺寸大于此值,选项会被截断而不报错;如果实际尺寸正好等于或者小于此值,那么返回时将此值更新为实际尺寸
16.7 带外数据
*带外数据(Out-of-band data)是一些通信协议所支持的可选特征,允许更高优先级的数据比普通数据优先传输。即使传输队列已经有数据,带外数据先行传输。TCP支持带外数据,但是UDP不支持
*TCP支持紧急标记(urgent mark)的概念:在普通数据流中紧急数据所在的位置
16.8 非阻塞和异步I/O
*通常,recv函数没有数据可用会阻塞等待。同样地,当套接字输出队列没有足够空间来发送消息时函数send会阻塞。在套接字非阻塞模式下,行为会改变。在这种情况下,这些函数不会阻塞而是失败,设置errno为EWOULDBLOCK或者EAGAIN。当这些发生时,可以使用poll或select来判断何时能接收或传输数据