1

在使用 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。我不知道为什么会这样……

4

1 回答 1

0

好吧,所以我找到了解决这个问题的“解决方案”。我仍然不知道它为什么会发生,如果这真的是一个解决方案,或者我以后是否会遇到其他问题。

另外,我不知道为什么这个解决方案有效。:D

无论如何,如果缓冲区不是成员函数而是为每次调用 ReceiveUDP 重新创建的,它就可以工作:

void AsynchronousServer::DoReceiveUDP()
{
    std::shared_ptr<std::array<char, 8192>> udp_receive_buffer;

    m_udp_socket.async_receive_from(boost::asio::buffer(*udp_receive_buffer, udp_receive_buffer->size()),
      udp::endpoint(), boost::bind<void>([this](boost::system::error_code error, std::size_t bytes_transferred,
    std::shared_ptr<std::array<char, 8192>> udp_receive_buffer)
    {
    }, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred, udp_receive_buffer));
}
于 2013-07-29T11:47:18.887 回答