为了获得更准确的答案,这里有详细且解释的代码。
首先,我们需要调用接收处理程序而不填充缓冲区。这是使用完成的boost::asio::null_buffer()
(see 反应堆式操作 http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/core/reactor.html欲了解更多信息,如坦纳所述)。
void UDPConnection::receive()
{
socket.async_receive(boost::asio::null_buffers(), receive_handler);
}
现在,当收到数据包时,receive_handler
将在没有任何缓冲区被填充的情况下被调用。
现在,对于处理程序:
void UDPConnection::handleReceive(const boost::system::error_code& error, unsigned int)
{
// Standard check: avoid processing anything if operation was canceled
// Usually happens when closing the socket
if(error == boost::asio::error::operation_aborted)
return;
With socket.available() http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/reference/basic_datagram_socket/available.html,我们可以得到要读取的字节数。重要提示:这个数字不一定是数据包的大小!对于我的测试,这个数字总是大于数据包大小(即使是 8 kB 的数据包,这是我的计算机可以处理的最大数据包)。
// Prepare buffer
unsigned int available = socket.available();
unsigned char* buffer = new unsigned char[available];
神奇的事情发生了:“真正的”接收调用在这里完成,并且通常会很快,因为它只会填充一个缓冲区。此调用只会使一个数据包出列(即使在调用时套接字中有多个数据包)。返回值在这里很重要,因为可能只填充了缓冲区的一部分。前任:可用=50,数据包大小=13.
// Fill it
boost::asio::ip::udp::endpoint senderEndpoint;
boost::system::error_code ec;
unsigned int packetSize = socket.receive_from(boost::asio::buffer(buffer, available), senderEndpoint, 0, ec);
现在,只需标准错误检查/处理/等等......
if(ec)
{
// ...
}
// Process packet
// ...
receive();
}