7、带外数据
带外数据是一个被一些通信协议支持的可选的特性,它允许比普通数据优先级高的数据被传送。带外数据会被优先任何已经排队的待传输的数据被传送。TCP支持带外数据,但是UDP不支持。TCP对带外数据的实现,会在很大的程度上影响用于带外数据的套接字接口。
TCP将带外数据看作"紧急(urgent)"数据。 TCP只支持单个字节的紧急数据 ,但是允许紧急数据通过普通的数据发送机制在带外发送。为了生成紧急数据,我们指定任意三个send函数的MSG_OOB标记,如果我们发送具有MSG_OOB标记的 数据大于一个字节,那么最后一个字节将会被当做紧急数据 。
当接收到紧急数据的时候,如果我们设置了由这个套接字产生相关信号,那么会发送给我们SIGURG信号。
前面我们可以看到,我们可以使用F_SETOWN命令fcntl函数设置一个套接字的属主。如果fcntl函数的第三个参数是整数,它指定一个进程ID,如果它是一个不是-1的负数,那么表示一个进程组ID。因此,我们可以通过调用如下函数,来让我们的应用程序接收信号:
fcntl(sockfd, F_SETOWN, pid);
F_GETOWN命令可以用来获取当前的套接字的属主。类似F_SETOWN命令,一个负数值表示进程组ID,一个正数值代表一个进程ID,所以如下调用:
owner = fcntl(sockfd, F_GETOWN, 0);
将会返回一个owner值,如果它是正数,则它与被配置接收套接字信号的进程ID相等;如果它是负数,则其绝对值与被配置从套接字接收信号的进程组ID相等。
TCP支持紧急标记的提示:就是紧急数据在普通数据流中出现的点。如果我们使用SO_OOBINLINE套接字选项,那么我们可以选择和普通数据在一起来接收紧急数据。为了能够辨别出我们已经到达了紧急标记点,我们使用sockatmark函数。
#include <sys/socket.h>
int sockatmark(int sockfd);
返回:如果到达了标记,那么返回1,如果没有到达标记那么返回0,如果出现了错误,那么返回1。
当下一个将要被读取的字节就是紧急数据标记的地方的时候,sockatmark将会返回1。
当带外数据在套接字读取队列中存在的时候,select函数将会返回这个文件描述符号,就像发生了提交的例外情况一样。我们可以选择连同普通数据一起来接收紧急数据,或者我们可以使用某个recv函数的MSG_OOB标记来在其他任何队列数据之前接收紧急数据。TCP会为一个字节的紧急数据排队,如果在我们接收到当前的紧急数据之前有另外的紧急数据到达,那么当前存在的紧急数据将会被忽略。
译者注
原文参考
8、非阻塞和异步I/O
一般来说recv函数将会在数据没有立即到达的时候阻塞。类似地,send函数将会在套接字用于发送的输出队列没有足够空间的时候阻塞。这个行为会在套接字处于非阻塞的模式的时候有所改变。这个时候,这些函数将会失败,并且设置errno为EWOULDBLOCK或者EAGAIN。当发生这个情况的时候,我们可以使用poll或者select函数来对我们能够发送或者接收数据时候进行处理。
Single UNIX Specification的实时扩展包含对通用的异步I/O机制的支持。套接字机制有它自己的处理异步I/O的方法,但是这个并没有在Single UNIX Specification中被标准化。有些文章将经典的基于套接字的异步I/O机制称为"基于信号的I/O",以和实时扩展的异步I/O机制进行区别。
使用基于套接字的异步I/O,我们可以设置在我们能够读取数据或者套接字的写队列中有空间的时候被发送SIGIO信号。激活异步I/O是一个两步的过程:
- 建立套接字属主,这样信号可以被发送到合适的进程。
- 通知套接字,我们想要它在I/O操作没有阻塞的时候给我们发送信号。
我们可以以三种方式完成第一个步骤:
- 使用fcntl函数的F_SETOWN命令。
- 使用ioctl函数的FIOSETOWN命令。
- 使用ioctl函数的SIOCSPGRP命令。
我们有两个选择可以完成第二个步骤:
- 使用fcntl函数的F_SETFL命令并且激活文件的O_ASYNC标记。
- 使用ioctl函数的FIOASYNC命令。
对于上面的那些命令,有一些但是它们并不是通用的。具体这些套接字异步I/O管理命令在哪个系统上支持,请参考参考资料中的一个表格,这里面就不列举出来了。
译者注
原文参考
9、总结
在本章,我们看到了允许进程像在本地机器一样与其他机器上的进程进行通信的进程通信机制。我们讨论了套接字末端如何被命名,以及我们在和服务端进行通信的时候怎样能够发现相应的地址信息。
我们展示了使用无连接方式(也就是基于数据报)的套接字和面向连接的套接字的例子。我们也简要地讨论了异步和非阻塞的套接字I/O以及用来管理套接字选项的接口。
在下一个章节中,我们将要看到一些高级的IPC内容,包含我们如何使用套接字在运行在同一台机器上面的进程之间传递文件描述符号。
网友评论