在URG标志为up的tcp段中,也可能存在正常数据。接收主机如何处理紧急数据包?如果它不是数据流的一部分,它如何确认紧急数据?它是否承认其余部分?
我知道它通常不常用,但如果两个主机都支持关于URG标志的相同RFC,它们如何处理带外数据?
如果紧急数据是中止消息,接收方将丢弃所有其他数据,但发送方仍希望确认已收到消息。
答案 0 :(得分:6)
一些背景知识:
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接收方都可以 为紧急指针实现相同的语义没有 将紧急指针指向"的功能差异 紧急数据后的八位字节序列号" vs."最后一个 紧急数据的八位字节",以及所有已知的实现解释 紧急指针的语义指向"序列 紧急数据后的八位字节数"。
因此更新RFC 793,RFC 1011和RFC 1122
紧急指针指向八位字节的序列号 关注紧急数据。
几乎满足所有现有的TCP实现。
注意:Linux提供net.ipv4.tcp_stdurg
sysctl
来覆盖默认行为,但此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,我发现在紧急数据的情况下没有什么特别的。
关于"紧急数据"
的长度几乎所有的实现都只能提供一个字节的#34;带外数据"。
RFC 6093说:
如果连续显示紧急数据"在收到之前收到 应用程序读取待处理的"带外"字节,即未决字节 将被丢弃(即被#34的新字节覆盖;紧急 数据"。)
因此TCP紧急模式及其紧急指针无法在实践中标明紧急数据的界限 有传言说有一些实现会对每个收到的紧急字节进行排队。他们中的一些人已经知道他们没有对他们排队的“紧急数据”数量施加任何限制。因此,它们容易受到微不足道的资源耗尽攻击。
P上。 S.所有上述内容可能比所要求的要多一些,但这只是为了让那些不熟悉这个问题的人明白。
一些更有用的链接:
TCP Urgent Pointer, buffer management, and the "Send" call
Difference between push and urgent flags in TCP
Understanding the urgent pointer