提升asio检测/避免接收缓冲区溢出

时间:2018-02-15 11:02:46

标签: c++ networking boost boost-asio

考虑客户端使用TCP将数据发送到服务器,使用boost :: asio,以“同步模式”(又称“阻塞”功能)。

客户端代码(跳过有关查询和io_service的部分):

tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::socket socket( io_service );
boost::asio::connect( socket, endpoint_iterator );
std::array<char, 1000> buf = { /* some data */ };
size_t n = socket.send( boost::asio::buffer(buf) );

这会将整个缓冲区(1000字节)发送到连接的机器。

现在服务器代码:

tcp::acceptor acceptor( io_service, tcp::endpoint( tcp::v4(), port ) );
tcp::socket socket( io_service );
boost::system::error_code err;
std::array<char, 500> buff;
size_t n = socket.read_some( boost::asio::buffer(buff), err );
std::cout << "err=" << err.message() << '\n';
  • 这是做什么的:客户端通过连接发送1000个字节,服务器尝试将其存储在500字节的缓冲区中。
  • 我的期望:服务器错误状态,说缓冲区太小和/或收到的数据太多。
  • 得到的结果:“成功”错误值,服务器中n = 1000。

我在这里想念什么? ASIO不能检测缓冲区溢出吗? 我应该继续使用其他一些类/功能(流,也许?)

参考(1.54,我使用的那个):

2 个答案:

答案 0 :(得分:1)

你严重误解了TCP。

TCP是一个字节流。 TCP流中没有数据包边界。在关闭套接字之前,所有字节都形成一个流。 (与UDP不同)

Boost.Asio知道这一点。只要流是开放的,它就不能说流最终会有多大。如果你有一个500字节的缓冲区,Boost Asio可以用(可能无界的)TCP流的前500字节填充它。

但是,read_some只关注已有的内容。在您的情况下,只需1000个字节,完全可以预期您的网卡上可以使用整个1000个字节。该部分没有错误。它不适合你的缓冲区,但这在网络方面不是问题。

TCP和UDP都没有办法回传接收器期望更小的数据包。这是应用程序级逻辑,您可以在应用程序级别处理它。例如,HTTP具有413 Payload Too Large。因此,Boost.Asio并没有提供标准机制。

答案 1 :(得分:0)

您确实收到了500个字节,并且可以通过再次调用asio来读取最后500个字节。只是这样说,因为在我看来你误解了asio的行为。