是否有标准调用将POSIX套接字的发送端一直刷新到远程端,或者这是否需要作为用户级协议的一部分实现?我环顾了常见的标题,却找不到任何东西。
答案 0 :(得分:25)
如何设置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 ...设置此选项会强制显式刷新待处理的输出...
所以可能最好在消息之后设置它,但不确定它在其他系统上是如何工作的
答案 1 :(得分:16)
对于Unix域套接字,您可以使用fflush()
,但我认为您可能意味着网络套接字。没有真正的冲洗概念。最接近的是:
在会话结束时,调用shutdown(sock, SHUT_WR)
关闭套接字上的写入。
在TCP套接字上,使用sockopt TCP_NODELAY
禁用Nagle算法,这通常是一个可怕的想法,即使它似乎在初步调查中处理它,也不能可靠地做你想要的。
处理任何问题都很可能是在用户协议级别上调用'flush'将是正确的。
答案 2 :(得分:7)
我无法在标准的TCP / IP套接字接口中知道将数据“一直刷到远端”并确保它已被实际确认。
一般来说,如果您的协议需要“实时”传输数据,通常最好的办法是设置setsockopt()
TCP_NODELAY
。这会禁用协议栈中的Nagle算法,并且套接字上的write()或send()更直接映射到网络上发送....而不是实现发送保持等待更多字节变为可用并使用所有TCP级别计时器决定何时发送。注意:关闭Nagle不会禁用TCP滑动窗口或任何东西,因此它总是安全的....但如果您不需要“实时”属性,数据包开销可能会上升很多。
除此之外,如果正常的TCP套接字机制不适合您的应用程序,那么通常您需要回退使用UDP并在UDP的基本发送/接收属性上构建自己的协议功能。当您的协议有特殊需求时,这是非常常见的,但是不要低估这样做的复杂性,并且除了相对简单的应用程序之外,在所有这些方面都要保持稳定和功能正确。作为一个起点,对TCP设计特征的深入研究将揭示需要考虑的许多问题。
答案 3 :(得分:7)
在RFC 1122中,您要查找的内容的名称是“PUSH”。 虽然我不知道任何实现“PUSH”的TCP API。
一些答案和评论涉及Nagle算法。他们中的大多数似乎都认为Nagle算法会延迟每次发送。这种假设是不正确的。仅当先前的数据包尚未被确认时,Nagle才会延迟发送(http://www.unixguide.net/network/socketfaq/2.11.shtml)。
为了简化一点:TCP尝试立即发送第一个数据包(一行数据包),但延迟后续数据包直到超时为止到达或第一个数据包被确认 - 以先发生者为准。
一种解决方案是避免这些“后续数据包”。如果您的应用程序调用send()多次传输单个复合请求,请尝试重写您的应用程序。在用户空间中汇编请求,然后调用send()
。一次。
此外,当发送缓冲区包含足够的数据来填充网络数据包的最大大小时,Nagle也不会延迟。这意味着,即使您将批量数据send()
分成小块,Nagle也不会(实际)延迟批量发送。
答案 4 :(得分:1)
我认为如果不是不可能正确实施那将是非常困难的。在这种情况下,“冲洗”是什么意思?字节传输到网络?接收方的TCP堆栈确认的字节数?字节传递给接收者的用户模式应用程序?字节是否完全由用户模式应用程序处理?
看起来您需要在应用级别执行此操作...
答案 5 :(得分:0)
TCP只提供尽力而为的交付,因此让所有字节离开机器A的行为是异步的,它们都是在机器B上接收的。当然,TCP / IP协议栈知道,但我不知道知道任何询问TCP堆栈的方法,以确定发送的所有内容是否已被确认。
到目前为止,处理问题的最简单方法是在应用程序级别。打开第二个TCP套接字作为反向通道,让远程伙伴向您发送确认信息,表明它已收到您想要的信息。它的成本是双倍的,但是可以完全移植,并且可以节省数小时的编程时间。
答案 6 :(得分:0)
您可以设置tcp选项SO_LINGER以设置特定超时,然后关闭套接字以确保在关闭连接时已发送所有数据(或检测到无法执行此操作)。除此之外,TCP是一种“尽力而为”的协议,并没有提供数据实际到达目的地的任何真正保证(与一些人似乎相信的相反),它只是尽力将其交付正确的顺序,并尽快。
答案 7 :(得分:0)
有一个 linux-specific way 可以在 TCP 套接字上执行此操作:
您不会强制 tcp 堆栈“立即发送数据”,但请记住您和内核正在尽可能快地发送数据。您可以使用 <!DOCTYPE html>
<html>
<head>
<%= title %>
</head>
<body>
<% image.forEach((image)=> { %>
<div>
<img src="data:image/<%=image.img.contentType%>;base64, <%=image.img.data.toString('base64')%>">
</div>
<% }) %>
</body>
</html>
稍微减少 send
和实际交付之间的延迟。
但基本上,通过执行 TCP_NODELAY
你已经完成了你的部分,你只需要等待 tcp 完成它的部分。
您可以在套接字上使用 send
和 ioctl
或 SIOCOUTQ
来查询交付状态并等待它完成。这应该足够了。特别是对于发送应用级数据包片段等用例。
答案 8 :(得分:-2)
使用fsync():
sock_fd是来自socket(...,...)call
的整数文件描述符FSYNC(sock_fd);