考虑客户端使用 TCP 和 boost::asio 以“同步模式”(也称为“阻塞”功能)向服务器发送数据。
客户端代码(略过query和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,这是我使用的那个):
最佳答案
你严重误解了 TCP。
TCP 是一个字节流。 TCP 流中没有数据包边界。在您关闭套接字之前,所有字节都形成一个流。 (与 UDP 不同)
Boost.Asio 知道这一点。只要stream是开着的,就不能说stream最终会有多大。如果你有一个 500 字节的缓冲区,Boost Asio 可以用(可能是无界的)TCP 流的前 500 个字节填充它。
但是,read_some
只是查看已经可用的内容。在您的情况下,只有 1000 个字节,完全可以预期整个 1000 个字节在您的网卡上可用。那部分没有错误。它只是不适合您的缓冲区,但这在网络端不是问题。
TCP 和 UDP 都没有办法回传接收者期待的是一个较小的数据包。那是应用程序级逻辑,你在应用程序级处理它。例如,HTTP 有 413 Payload Too Large
。因此,Boost.Asio 不提供标准机制。
关于c++ - boost asio检测/避免接收缓冲区溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48805652/