1.带外数据
转自:https://www.cnblogs.com/c-slmax/p/5553857.html
传输层协议使用带外数据(out-of-band,OOB)来发送一些重要的数据,如果通信一方有重要的数据需要通知对方时,协议能够将这些数据快速地发送到对方。
TCP协议没有真正意义上的带外数据.为了发送重要协议,TCP提供了一种称为紧急模式(urgentmode)的机制。
TCP协议在数据段中设置URG位,表示进入紧急模式.接收方可以对紧急模式采取特殊的处理.很容易看出来,这种方式数据不容易被阻塞,
可以通过在我们的服务器端程序里面捕捉SIGURG信号来及时接受数据或者使用带OOB标志的recv函数来接受。
2.意义与使用情况
一个流套接口会有一个大量的数据队列等待发送到网络。在远程端点,也会有大量已接收的,却还没有被 程序读取的数据。
如果发送客户端程序由于一些原因需要取消已经写入服务器的请求,那么他就需要向服务器紧急发送一个标识取消的请求。如果向远程服务器发送 取消请求失败,那么就会无谓的浪费服务器的资源。
使 用带外数据的实际程序例子就是telnet,rlogin,ftp命令。前两个程序会将中止字符作为紧急数据发送到远程端。这会允许远程端冲洗所有未处理 的输入,并且丢弃所有未发送的终端输出。这会快速中断一个向我们屏幕发送大量数据的运行进程。ftp命令使用带外数据来中断一个文件的传输。
带外数据对应到TCP头部的紧急数据URG位。
3.发送端与接收端
3.1 发送端
-
紧急数据是插在正常数据流中进行传输的 。
- 一个紧急指针只指向一个字节的带外数据的后一个字节位置。
- 即使数据的流动会因为
TCP
的流量控制而停止,紧急通知却总是无障碍的发送到对端TCP
。 -
带外字节会被标记为
OOB。(怎么标记?在哪里标记?)
3.2 接收端
一旦有一个新的紧急指针到达,不论由紧急指针指向的实际数据字节是否已经到达接受端,以下两个动作都会发生 :
-
当接受到一个设置了
URG
标志的分节时,接受端检查紧急指针,确定它是否指向新的带外数据,比如:前面发送了两个包,只有第一个才会通知接受进程有新的带外数据到达。 -
当有新的紧急指针到达时,接受进程被通知到。首先,内核会给接受套接字的属主进程发送
SIGURG
信号,前提是接受进程调用了fcntl
或者ioctl
为这个套接字建立了属主,并且该属主进程为该信号建立了信号处理函数 。 -
当由紧急指针指向的实际数据字节到达接受端
TCP
时,数据字节会有两个存储地区:一个是和普通数据一样的在线留存,另外一个是独立的单字节带外缓冲区,接受进程从这个单字节带外缓冲区读入数据的唯一方法是指定MSG_OOB
调用recv
,recvfrom
,recvmsg
。
4. 为何不直接将一个字节的紧急数据放在紧急指针哪里呢?
因为TCP数据包在ip层可能被拆包,成为多个数据段。一个包含紧急数据的数据包被拆成两个数据包,那么这两个包有的tcp头部有相同的紧急指针(和UGR)。如果将紧急数据直接放在紧急指针的内存处,那么将多出一个紧急数据!所以,不该将紧急数据放在TCP头部。
拆包后,多个数据段包含相同的头部,那么一个字节的紧急数据也会被包含在多个头部,就将多出一个紧急数据。
//那么多出紧急数据又有什么危害呢?
5.总结
带外数据概念实际上是向接收端传送三个不同的信息:
1.发送端进入紧急模式这个事实。要么是通过SIGURG信号或者select监听异常事件
2.带外字节的位置,也就是它相对于来自发送端的其余数据的发送位置:带外标记。
3.带外字节的实际值。既然TCP是一个不解释应用进程所发送数据的字节流协议,带外字节就可以是任何8位值。
- 每个连接只有一个TCP紧急指针;
- 每个连接只有一个带外标记;
- 每个连接只有一个单字节的带外缓冲区