一点背景:
TCP 紧急机制允许将数据流中的一个点指定为紧急信息的结尾。因此,我们有一个紧急指针,它包含与此 tcp 段中的序列号的正偏移量。该字段仅在设置了 URG 控制位时才有意义。
关于紧急指针的差异:
RFC 793(1981,第 17 页):
紧急指针指向八位字节的序号
紧跟紧急数据。
RFC 1011(1987 年,第 8 页):
第 17 页是错误的。紧急指针指向最后一个八位字节
紧急数据(不是非紧急数据的第一个八位字节)。
RFC 1122(1989,第 84 页)中的相同内容:
..紧急指针指向最后一个八位字节的序列号
(不是 LAST+1)在一系列紧急数据中。
可理解的RFC 6093(2011,第 6-7 页)说:
考虑到只要 TCP 发送方和 TCP 接收方
为紧急指针实现相同的语义没有
使紧急指针指向“
紧跟在紧急数据后面的八位字节的序列号”与“最后一个
紧急数据的八位字节”,并且所有已知的实现都解释
紧急指针的语义指向“序列
紧急数据后面的八位字节数"。
因此更新 RFC 793、RFC 1011 和 RFC 1122 是
紧急指针指向八位字节的序号
关注紧急数据。
它几乎满足所有现有的 TCP 实现。
注意:Linux 提供了net.ipv4.tcp_stdurgsysctl 来覆盖默认行为,但这个sysctl 只影响传入段的处理。传出段中的紧急指针仍将按照 RFC 793 中的规定进行设置。
关于数据处理
您可以通过两种方式获取紧急数据(请记住,TCP 的“紧急数据”概念作为“带外数据”映射到套接字 API):
-
使用 recv 和 MSG_OOB 标志集。
(通常您应该使用fcntl(sock, F_SETOWN, getpid()); 之类的东西建立套接字的所有权,并为SIGURG 建立信号处理程序)。因此,您将收到SIGURG 信号通知。数据将与普通数据流分开读取。
-
使用 recv 而不设置 MSG_OOB 标志。以前,您应该这样设置SO_OOBINLINE 套接字选项:
int so_oobinline = 1; /* true */
setsockopt(sock, SOL_SOCKET, SO_OOBINLINE, &so_oobinline, sizeof so_oobinline);
数据保持“在线”。您可以在ioctl 的帮助下确定紧急指针:
int flag; /* True when at mark */
ioctl(sock, SIOCATMARK, &flag);
除了recommended 对于新应用程序根本不使用紧急数据机制使用(如果是)内联接收,如上所述。
来自 RFC 1122:
TCP 紧急机制不是发送“带外”的机制
数据:所谓的“紧急数据”应该“在线”传递给
TCP 用户。
同样来自 RFC 793:
TCP 不会尝试定义用户具体做什么
收到待处理紧急数据的通知
所以你可以随心所欲地处理。这是一个应用程序级别的问题。
因此,关于删除所有其他数据时的确认问题的答案是“您可以在您的应用程序中实现它”。
至于tcp-ack,在紧急数据的情况下,我没发现有什么特别之处。
关于“紧急数据”的长度
几乎所有的实现都只能提供一个字节的“带外数据”。
RFC 6093 说:
如果在发送前收到“紧急数据”的连续指示
应用程序读取挂起的“带外”字节,即挂起的字节
将被丢弃(即被“紧急”的新字节覆盖
数据”)。
所以 TCP 紧急模式及其紧急指针在实践中无法提供紧急数据边界的标记。
有传言说有一些实现将每个接收到的紧急字节排队。众所周知,他们中的一些人未能对他们排队的“紧急数据”数量实施任何限制。因此,它们很容易受到微不足道的资源耗尽攻击。
P。 S. 以上所有内容可能比所要求的要多一些,但这只是为了让不熟悉这个问题的人清楚。
一些更有用的链接:
TCP Urgent Pointer, buffer management, and the "Send" call
Difference between push and urgent flags in TCP
Understanding the urgent pointer