是否有标准调用将POSIX套接字的发送端一直刷新到远程端,还是需要将其作为用户级协议的一部分实现?我环顾了常见的标题,却找不到任何东西.
怎么样设置TCP_NODELAY而不是重新设置它?可能它可以在发送重要数据之前完成,或者在我们完成发送消息之后完成.
send(sock, "notimportant", ...); send(sock, "notimportant", ...); send(sock, "notimportant", ...); int flag = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)); send(sock, "important data or end of the current message", ...); flag = 0; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
正如linux手册页所说
TCP_NODELAY ...设置此选项会强制显式刷新挂起的输出...
所以可能最好在消息之后设置它,但不确定它在其他系统上是如何工作的
对于Unix域套接字,您可以使用fflush()
,但我认为您可能意味着网络套接字.没有真正的冲洗概念.最接近的是:
在会话结束时,调用shutdown(sock, SHUT_WR)
关闭套接字上的写入.
在TCP套接字上,使用sockopt禁用Nagle算法TCP_NODELAY
,这通常是一个糟糕的想法,即使它似乎在初始调查中处理它,也无法可靠地执行您想要的操作.
处理用户协议级别的"刷新"问题很可能是正确的.
在标准的TCP/IP套接字接口中,我无法清楚地将数据"一直刷到远程端",并确保它已被实际确认.
一般来说,如果你的协议有需要的数据的"实时"传输,一般做的最好的事情是设置setsockopt()
的TCP_NODELAY
.这会禁用协议栈中的Nagle算法,并且套接字上的write()或send()更直接映射到网络上发送....而不是实现发送保持等待更多字节变为可用并使用所有TCP级别计时器决定何时发送.注意:关闭Nagle不会禁用TCP滑动窗口或任何东西,因此它总是安全的....但如果您不需要"实时"属性,数据包开销可能会上升很多.
除此之外,如果正常的TCP套接字机制不适合您的应用程序,那么通常您需要回退使用UDP并在UDP的基本发送/接收属性上构建自己的协议功能.当您的协议有特殊需求时,这是非常常见的,但是不要低估这样做的复杂性,并且除了相对简单的应用程序之外,在所有协议中都要保持稳定和功能正确.作为一个起点,对TCP设计特征的深入研究将揭示需要考虑的许多问题.
在RFC 1122中,您要查找的东西的名称是"PUSH".虽然我不知道任何实现"PUSH"的TCP API.
一些答案和评论涉及Nagle算法.他们中的大多数似乎都认为Nagle算法会延迟每次发送.这种假设是不正确的.Nagle仅在先前的数据包尚未被确认时延迟发送(http://www.unixguide.net/network/socketfaq/2.11.shtml).
为了简化它一点点:TCP试图发送的第一个数据包(包的行的)立即,但是会延迟后续报文直到达到超时或第一个数据包被确认-以先到者为准.
一种解决方案是避免这些"后续数据包".如果您的应用程序调用send()多次传输单个复合请求,请尝试重写您的应用程序.在用户空间中组装请求,然后调用send()
.一旦.
此外,当发送缓冲区包含足够的数据来填充网络数据包的最大大小时,Nagle也不会延迟.这意味着,即使您send()
将批量数据分成小块,Nagle也不会(真正)延迟批量发送.