在使用 boost 库编写同时支持 TCP 和 UDP 的服务器时,我遇到了一个奇怪的问题:服务器收到任何 UDP 消息后,如果我尝试将 std::cin (或 std::getline)调用输入到字符串中。
这仅在收到至少一条 UDP 消息后才会发生。我不知道这里会发生什么,因为收到消息时我几乎不做任何事情。我打破了重要的代码:
void AsynchronousServer::DoReceiveUDP()
{
m_udp_socket.async_receive_from(boost::asio::buffer(m_udp_receive_buffer,
m_udp_receive_buffer.size()),
udp::endpoint(), [this](boost::system::error_code error, std::size_t
bytes_transferred)
{
});
}
DoReceiveUDP() 方法在服务器启动时和 io_service.run() 之前被调用。通常它会做更多的事情(例如再次调用自身),但出于测试目的,我将所有内容都注释掉了,因此它实际上只接收一次。m_udp_receive_buffer 是一个
std::array<char, 8196>
,AsynchronousServer 类的一个属性,在其他任何地方都没有使用。
在主线程中,这是我在设置服务器后真正要做的事情:
while(true)
{
std::string message;
std::getline(std::cin, message); //On this line the program crashes
//server.SendMessageTCP(1, message);
}
现在正如我所说,崩溃(调试消息说缓冲区溢出)仅在通过 UDP 接收到消息后发生。我的服务器还通过 async_read 读取 TCP 消息。但这不会引起错误。
我还测试了这一点,将 getline-input 存储在一个恒定大小的数组中,效果很好。但我真的不能这样做,因为我不知道消息有多长,这意味着当我发送消息时缓冲区充满了很多无用的字符。此外,无论如何发生这样的奇怪事情,我真的不觉得安全,宁愿解决问题也不愿绕过它。
你们中有人对这里可能出现的问题有什么想法吗?如果您需要更多代码,请问,但我想我已经发布了所有相关的内容。:)
编辑:我也注释掉了错误代码和传输的字节,但它是“完整”版本。我没有收到任何错误,传输的字节正是消息的长度。
经过更多的测试,我至少可以猜测更多。如果我希望通过 cin 输入输入并且在此期间收到一条消息,则似乎会出现问题。
例如,如果我这样做:
while(true)
{
std::string message;
boost::this_thread::sleep(boost::posix_time::seconds(3));
std::getline(std::cin, message);
}
并且客户端在线程休眠的这三秒钟内发送了一条 UDP 消息,一切正常。如果三秒钟过去了,然后收到消息,它会像以前一样崩溃。
但是,有一个非常奇怪的行为:在我在这三秒钟内发送了一条 UDP 消息后,程序将不再崩溃——即使我等待下一条消息,直到线程再次到达 getline。我不知道为什么会这样……