首页 文章

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

提问于
浏览
2

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

只有在调用了前一个请求的“on write”处理程序时,Writer才会执行每个连续的async_write请求 .

问题是,如果Writer(客户端)将更多数据写入套接字而不是Reader(服务器)能够接收到这似乎是行为:

  • Writer将开始写入(我认为)系统缓冲区,即使读取器尚未接收到数据,它也将调用“on write”处理程序而不会出现错误 .

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

  • 同时,Reader仍在接收小块数据 .

  • 在关闭Writer程序后,Reader继续接收字节的事实似乎证明了这个理论是正确的 .

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

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

我认为可以想到的第一个解决方案是使用UDP而不是TCP . 这是 will 就是这样,因为我将来会有类似的问题 .

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

NOTE2 :这是一个演示问题的工作示例:http://pastie.org/3122025

EDIT :我已经做了一个测试,在我的NOTE1中我提到当我使用asio :: iosockets时我没有遇到过这种缓冲 . 所以我想确定并创建了这个测试:http://pastie.org/3125452事实证明 the buffering is there event with asio::iosockets ,所以一定有其他东西导致它顺利进行,可能更低的FPS .

1 回答

  • 2

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

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

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

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

相关问题