分类:
2012-05-16 13:05:58
原文地址:APUE读书笔记-16网络通信-07带外数据 作者:vaqeteart
++++++APUE读书笔记-16网络通信-07带外数据++++++
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
int sockatmark(int sockfd);
返回:如果到达了标记,那么返回1,如果没有到达标记那么返回0,如果出现了错误,那么返回1。
当下一个将要被读取的字节就是紧急数据标记的地方的时候,sockatmark将会返回1。
当带外数据在套接字读取队列中存在的时候,select函数将会返回这个文件描述符号,就像发生了提交的例外情况一样。我们可以选择连同普通数据一起来接收紧急数据,或者我们可以使用某个recv函数的MSG_OOB标记来在其他任何队列数据之前接收紧急数据。TCP会为一个字节的紧急数据排队,如果在我们接收到当前的紧急数据之前有另外的紧急数据到达,那么当前存在的紧急数据将会被忽略。
参考: