当前位置:  开发笔记 > 前端 > 正文

有没有办法刷新POSIX套接字?

如何解决《有没有办法刷新POSIX套接字?》经验,为你挑选了4个好方法。

是否有标准调用将POSIX套接字的发送端一直刷新到远程端,还是需要将其作为用户级协议的一部分实现?我环顾了常见的标题,却找不到任何东西.



1> fantastory..:

怎么样设置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 ...设置此选项会强制显式刷新挂起的输出...

所以可能最好在消息之后设置它,但不确定它在其他系统上是如何工作的


我确认它有效.我喜欢在发送"重要数据或当前消息结束"后设置和重置TCP_DELAY,因为它允许将这些内容放入flush套接字方法中.

2> chaos..:

对于Unix域套接字,您可以使用fflush(),但我认为您可能意味着网络套接字.没有真正的冲洗概念.最接近的是:

    在会话结束时,调用shutdown(sock, SHUT_WR)关闭套接字上的写入.

    在TCP套接字上,使用sockopt禁用Nagle算法TCP_NODELAY,这通常是一个糟糕的想法,即使它似乎在初始调查中处理它,也无法可靠地执行您想要的操作.

处理用户协议级别的"刷新"问题很可能是正确的.


我没有看到为什么禁用Nagle算法"通常是一个可怕的想法".如果您知道它的作用,那么有许多应用程序协议情况,禁用Nagle正是您想要做的.我怀疑你没有真正需要这样做的情况,或者你不明白它的真正含义.换句话说,这个功能是有原因的,它也可能因为一个很好的理由而被禁用.
`fflush`与unix域套接字的问题无关.只有你通过`fdopen`用`FILE`包装套接字才有意义...
我所做的是启用Nagle,尽可能多地写入字节(使用非阻塞I/O)到套接字(即直到我用完要发送的字节,或者send()调用返回EWOULDBLOCK,以先到者为准) ,然后再次禁用Nagle.这看起来效果很好(即我尽可能获得低延迟和全尺寸数据包)
如果有TCP刷新,Nagle可能是一件很棒的事情.因为它可以将其缓冲区大小优化为当前段大小.如果您禁用nagle,则您拥有自己的缓冲区,该缓冲区未与段大小同步,因此您将通过网络发送半满的数据包...

3> Tall Jeff..:

在标准的TCP/IP套接字接口中,我无法清楚地将数据"一直刷到远程端",并确保它已被实际确认.

一般来说,如果你的协议有需要的数据的"实时"传输,一般做的最好的事情是设置setsockopt()TCP_NODELAY.这会禁用协议栈中的Nagle算法,并且套接字上的write()或send()更直接映射到网络上发送....而不是实现发送保持等待更多字节变为可用并使用所有TCP级别计时器决定何时发送.注意:关闭Nagle不会禁用TCP滑动窗口或任何东西,因此它总是安全的....但如果您不需要"实时"属性,数据包开销可能会上升很多.

除此之外,如果正常的TCP套接字机制不适合您的应用程序,那么通常您需要回退使用UDP并在UDP的基本发送/接收属性上构建自己的协议功能.当您的协议有特殊需求时,这是非常常见的,但是不要低估这样做的复杂性,并且除了相对简单的应用程序之外,在所有协议中都要保持稳定和功能正确.作为一个起点,对TCP设计特征的深入研究将揭示需要考虑的许多问题.



4> hagello..:

在RFC 1122中,您要查找的东西的名称是"PUSH".虽然我不知道任何实现"PUSH"的TCP API.

一些答案和评论涉及Nagle算法.他们中的大多数似乎都认为Nagle算法会延迟每次发送.这种假设是不正确的.Nagle仅在先前的数据包尚未被确认时延迟发送(http://www.unixguide.net/network/socketfaq/2.11.shtml).

为了简化它一点点:TCP试图发送的第一个数据包(包的行的)立即,但是会延迟后续报文直到达到超时或第一个数据包被确认-以先到者为准.

一种解决方案是避免这些"后续数据包".如果您的应用程序调用send()多次传输单个复合请求,请尝试重写您的应用程序.在用户空间中组装请求,然后调用send().一旦.

此外,当发送缓冲区包含足够的数据来填充网络数据包的最大大小时,Nagle也不会延迟.这意味着,即使您send()将批量数据分成小块,Nagle也不会(真正)延迟批量发送.

推荐阅读
手机用户2402851335
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有