【发布时间】:2013-07-27 18:43:30
【问题描述】:
在使用 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。我不知道为什么会这样......
【问题讨论】:
-
您没有检查 async_receive_from 处理程序中的错误参数。同样,接收了多少字节?
-
是的,我也对此发表了评论,但它是“完整”版本。我没有收到任何错误代码。收到的字节正是消息的长度。
-
您可能遇到了对象生命周期问题,请发布
AsynchronousServer的定义。