boost :: asio比通过TCP接收更快地发送数据。或者如何禁用缓冲

时间:2012-01-04 01:34:22

标签: boost asynchronous tcp boost-asio buffering

我创建了一个客户端/服务器程序,客户端启动 Writer类的一个实例,服务器启动一个实例 读者课。然后Writer将写入DATA_SIZE字节的数据 每个USLEEP mili秒都与读者异步。

Writer完成每个连续的async_write请求 仅当前一个请求的“on write”处理程序有 被叫了。

问题是,如果Writer(客户端)正在写入更多数据 套接字比Reader(服务器)能够接收这个似乎 成为行为:

  • Writer将开始写入(我认为)系统缓冲区甚至 虽然读者尚未收到数据,但它将会是 在没有错误的情况下调用“on write”处理程序。

  • 当缓冲区已满时,boost :: asio不会触发“on write” 处理程序,直到缓冲区变小。

  • 与此同时,读者仍在接收小块 数据。

  • 我关闭后Reader继续接收字节的事实 作家计划似乎证明了这一理论的正确性。

我需要实现的是防止这种缓冲,因为 数据需要“实时”(尽可能多)。

我猜我需要使用一些套接字选项的组合 asio提供,像no_delay或send_buffer_size,但我只是在猜测 在这里,因为我没有成功地试验这些。

我认为人们可以想到的第一个解决方案是使用 UDP而不是TCP。这个成为我需要切换到的情况 UDP也出于其他原因在不久的将来,但我会 首先想知道如何用TCP做到这一点 把它直接放在我的头上,以防万一我会有类似的 将来某些问题。

NOTE1 :在我开始尝试在asio库中进行异步操作之前,我已经使用线程,锁和asio :: sockets实现了同样的场景,并且当时没有经历过这样的缓冲。我不得不切换到异步API,因为asio似乎不允许同步调用的定时中断。

NOTE2 :以下是演示此问题的工作示例:http://pastie.org/3122025

编辑:我已经做了一个测试,在我的NOTE1中我提到当我使用asio :: iosockets时我没有遇到过这种缓冲。所以我想确定并创建了这个测试:http://pastie.org/3125452事实证明缓冲是有asio :: iosockets 的事件,所以必定还有其他东西导致它去了顺利,可能会降低FPS。

1 个答案:

答案 0 :(得分:2)

TCP / IP绝对适合最大化吞吐量,因为大多数网络应用程序的意图是在主机之间传输数据。在这种情况下,预计N个字节的传输将花费T秒,并且显然接收器处理数据的速度有点慢并不重要。实际上,正如您所注意到的那样,TCP / IP协议实现了滑动窗口,该窗口允许发送器缓冲一些数据,以便始终可以发送它,但最终节流控制留给接收器。接收器可以全速前进,自行调整甚至暂停传输。

如果您不需要吞吐量而是希望保证发送方传输的数据尽可能接近实时,那么您需要确保发送方不会写下一个数据包直到他从接收器接收它已处理先前数据包的确认。因此,不要盲目地在数据包之后发送数据包直到被阻止,而是定义一个消息结构,用于将控制消息从接收方发送回发送方。

显然,通过这种方法,您的权衡是每个发送的数据包更接近发送方的实时,但您限制了可以传输的数据量,同时略微增加协议使用的总带宽(即附加控制消息) 。还要记住,“接近实时”是相对的,因为您仍将面临网络延迟以及接收器处理数据的能力。因此,您还可以查看特定应用程序的设计约束,以确定您确实需要“接近”。

如果您需要非常接近,但同时您不关心数据包是否丢失,因为旧数据包数据被新数据取代,那么UDP / IP可能是更好的选择。但是,a)如果你有可靠的交付要求,你最终可能会重新发明tcp / ip轮的一部分; b)请记住,某些网络(企业防火墙)倾向于阻止UDP / IP,同时允许TCP / IP流量和c )甚至UDP / IP都不是完全实时的。