TCP带外数据

             企者不立,跨者不行,自见者不明,自是者不彰,自伐者无功,自矜者不长。--《老子》


带外数据(out-of-band data),有时也称为 经加速数据(expedited data)。其想法是一个连接的某段发生了重要的事情,而且该端希望迅速通告其对端。 这里迅速,意味着这种通知应该在已经排队等待发送的任何普通数据(有时也称带内数据)之前发送。也就是说,带外数据被认为具有比普通数据更高的优先级。

带外数据并不要求在客户和服务器之间再使用一个连接,而是被映射到已有的连接中。

几乎每种传输层都有各自不同的带外数据实现。 UDP作为一个特例,没有实现带外数据。下面主要讲述TCP的带外数据。


TCP带外数据:

TCP并没有真正的带外数据,但是提供了紧急模式(urgent mode)。假设一个进程已经向一个TCP套接字写出N字节数据,而且TCP把这些数据排队在该套接字的发送缓冲区中,等待着发送到对端。下图展示了这样的套接字发送缓冲区,并且标记了从1到N的数据字节。

该进程接着以MSG_OOB标志调用send函数写出一个含有字符a的单字节带外数据:

send(fd, "a",1,MSG_OOB);

TCP把这个数据放置在该套接字发送缓冲区的下一个可用位置,并把该连接的TCP紧急指针(urgent pointer)设置成再下一个可用位置。 (TCP紧急指针的意义?)  , 下图展示了此时的套接字发送缓冲区,并且把带外字节标记为“OOB”。

给定如上图所示的套接字发送缓冲区状态,发送端TCP将为待发送的下一个分节在TCP首部中设置URG标志,并把紧急偏移字段设置为指向带外字节之后的字节,,不过该分解可能包含也可能不包含我们标记为OOB的那个字节。  OOB字节是否发送取决于套接字发送缓冲区先于它的字节数、TCP准备发送给对端的分节大小以及对端通告的当前窗口。

 

TCP紧急模式的一个重要特点: TCP首部指出发送端已经进入紧急模式(即伴随紧急偏移的URG标志已经设置),但是由紧急指针所指的实际数据字节不一定随同送出。 事实上,即使发送端TCP因流量控制而暂停发送数据(接收端的套接字接受缓冲区已满,导致其TCP向发送端TCP通告了一个值为0的窗口),紧急通知照样不伴随任何数据地被发送! 这也是TCP应用进程使用TCP紧急模式(即带外数据)的一个原因即使数据的流动会因为TCP流量控制而停止,紧急通知却总是无障碍地发送到对端TCP。

如果,我们发送多字节的带外数据,情况又会如何呢?例如:

send(fd,"abc",3, MSG_OOB); 则,TCP的紧急指针指向最后那个字节后面的位置。


讲完了带外数据的发送,下面从接收端的角度查看一下:

1)当接收到一个设置了URG标志的分节时,接收端TCP检查紧急指针,确定它是否指向新的带外数据,也就是判断本分节是不是首个到达的紧急模式分节。 发送端TCP往往发送多个含有URG标志且紧急指针指向同一个数据字节(如何实现的) 的分节(通常是在一小段时间内),这些分节中只有第一个到达的会导致系统通知接收进程有新的带外数据到达。

2)当有新的紧急指针到达时,接收进程被通知。首先,内核给接收套接字的属主进程发送SIGURG信号,前提是接收进程 或其他进程层调用fcntl或ioctl为这个套接字建立了属主, 而且该属主进程为这个信号建立了信号处理函数。 其次,如果接收进程阻塞在select调用中以等待这个套接字描述符出现一个异常条件,select调用就返回。

      一旦有新的紧急指针到达,不论由紧急指针指向的实际数据字节是否已经到达接收端TCP,上述信号处理函数会触发,select调用返回。

      只有一个OOB标记,如果新的OOB字节在旧的OOB字节被读取之前就到达,旧的OOB字节就被丢弃。

3)当仅仅指针指向的实际数据字节到达接收端TCP时,该数据字节既可能被拉出带外,也肯能被留在带内,即在线留存。SO_OOBINLINE套接字选项默认情况下是禁止的,对于这样的接收端套接字,该数据字节并不放入套接字缓冲区,而是被放入该连接的一个独立的单字节带外缓冲区,接收进程从这个单字节缓冲区中读取数据的唯一方法是制定MSG_OOB标志,调用recv,recvfrom或recvmsg。

然而,如果接收进程开启了SO_OOBINLINE套接字选项,那么由TCP紧急指针指向的实际数据字节将被留在通常的套接字接收缓冲区中。这种情况下,接受进程不能指定MSG_OOB标志来读入该数据字节。相反,接收进程通过检查该连接的带外标记以获悉何时访问到这个数据字节(章节24.3)。

发生一些错误的情况:

1)如果接收进程请求读入带外数据(通过指定MSG_OOB标志),但是对端尚未发送任何带外数据,读入操作将返回EINVAL.

2) 在接收进程已被告知对端发送了一个带外字节(通过SIGURG或select手段)的前提下,如果接收进程试图读入该字节,但是该字节尚未到达,读入操作将返回EWOULDBLOCK。 接收进程此时能做的仅仅是从套接字接收缓冲区读入数据(要是没有存放这些数据的空间,可能还得丢弃它们),以便在该缓冲区中腾出空间,继而允许对端tcp发送出那个带外字节。

3)如果接收进程试图多次读入同一个带外字节,读入操作将返回EINAVAL;

4) 如果接收进程已经开启了SO_OOBINLINE套接字选项,但却试图通过指定MSG_OOB标志来读入带外数据,读入操作将返回EINVAL。

 


TCP紧急指针的意义?

TCP紧急指针对应一个TCP序列号,是 使用MSG_OOB标志写出的最后一个字节对应的序列号加1.


Ref:

《Unix网络编程 卷一》,24章

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

First Snowflakes

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值