C++ 多线程UDP服务器中io_上下文或std::cout的奇怪行为

C++ 多线程UDP服务器中io_上下文或std::cout的奇怪行为,c++,multithreading,boost,cout,asio,C++,Multithreading,Boost,Cout,Asio,我使用boost\asio创建了一个简单的UDP服务器,目前只打印接收到的数据,如下所示 using boost::asio::ip::udp; enum { max_length = 2048 }; void server(boost::asio::io_context& io_context, unsigned short port) { std::cout << "Server Created on port " + std::to_string(port)

我使用boost\asio创建了一个简单的UDP服务器,目前只打印接收到的数据,如下所示

using boost::asio::ip::udp;

enum { max_length = 2048 };

void server(boost::asio::io_context& io_context, unsigned short port)
{
    std::cout << "Server Created on port " + std::to_string(port) << " \n" << std::flush;
    udp::socket sock(io_context, udp::endpoint(udp::v4(), port));
    while(true)
    {
        udp::endpoint sender_endpoint;
        std::vector<char> v(max_length);
        sock.receive_from(boost::asio::buffer(v), sender_endpoint);
        for (int i = 0; i < v.size(); i++)
        {
            std::cout << v[i] <<std::flush;
        }
        std::cout << std::endl;
    }
}
测试我使用的服务器。问题是输出是。。。爬。
当以差不多每秒一次的速度在3个端口上发送数据包时,输出稍微错位,但当将数据包频率增加到每0.1秒一次时,输出将变得不可读,如中所示。我曾尝试为每台服务器提供一个单独的io_上下文对象,但在高频率下输出保持不变。有没有办法避免这种情况

合乎逻辑且正确的解决方案是在std::cout上使用互斥。在您的情况下,您知道锁的适当范围,只是一个UDP数据包,但std::cout无法猜到这一点


奇特的解决方案是。对于这样的简单情况,您不需要这样做,但是由于您试图使用boost.asio.io_上下文,您应该知道boost.asio中还有另一个类可以像您预期的那样工作。

逻辑正确的解决方案是在std::cout上使用互斥。在您的情况下,您知道锁的适当范围,只是一个UDP数据包,但std::cout无法猜到这一点

奇特的解决方案是。对于这样的简单情况,您不需要这样做,但由于您正在尝试使用boost.asio.io_上下文,您应该知道boost.asio中还有另一个类可以像您预期的那样工作。

std::cout自动为您执行一些锁定,单个打印操作不会与来自不同线程的另一个打印重叠。但是,当您一次打印一个字符时,每个线程的输出可能会重叠。在每个打印字符之后刷新也可能导致性能不佳

如果将要打印的内容生成为单个字符串,则应正确打印:

    std::vector<char> v(max_length);
    size_t bytes = sock.receive_from(boost::asio::buffer(v), sender_endpoint);
    std::string str(v.data(), bytes);
    str += '\n';
    std::cout << str;
或者可以跳过向量并直接保存为字符串:

    std:: string str(max_length);
    size_t bytes = sock.receive_from(boost::asio::buffer(str), sender_endpoint);
    str.resize(bytes)
    str += '\n';
    std::cout << str;
std::cout自动为您执行一些锁定,单个打印操作不会与来自不同线程的另一个打印重叠。但是,当您一次打印一个字符时,每个线程的输出可能会重叠。在每个打印字符之后刷新也可能导致性能不佳

如果将要打印的内容生成为单个字符串,则应正确打印:

    std::vector<char> v(max_length);
    size_t bytes = sock.receive_from(boost::asio::buffer(v), sender_endpoint);
    std::string str(v.data(), bytes);
    str += '\n';
    std::cout << str;
或者可以跳过向量并直接保存为字符串:

    std:: string str(max_length);
    size_t bytes = sock.receive_from(boost::asio::buffer(str), sender_endpoint);
    str.resize(bytes)
    str += '\n';
    std::cout << str;

我对boost知道的不多,所以我可能在谈论wazoo。这有用吗?我觉得解决方案应该是使用一个共享的cout互斥,并将其传递给每个线程。io_上下文与std::cout没有关系。您需要使用一些同步方法来避免混乱。例如,可以使用std::mutex并在std::cout@sklott事实上,除非@Mgetz仔细阅读,否则您不会看到多个线程输出的单个字符可能会交错,但不会发生数据竞争。我对boost不太了解,所以我可能在谈论wazoo。这有用吗?我觉得解决方案应该是使用一个共享的cout互斥,并将其传递给每个线程。io_上下文与std::cout没有关系。您需要使用一些同步方法来避免混乱。例如,可以使用std::mutex并在std::cout@sklott事实上,除非@Mgetz仔细阅读,否则您不会看到多个线程输出的单个字符可能会交错,但不会发生数据竞争,令人惊讶的是,我竟然没有想到这一点。非常感谢。哇,太神奇了,我怎么都没想到。非常感谢。但是,我尝试使用strand,因为我还没有明确地调用io_context.run,所以它不起作用。不过,我以后发布数据时肯定需要它,谢谢。我尝试使用strand,但是,因为我还没有明确地调用io_context.run,所以它不起作用。不过,当我以后发布数据时,我确实需要它,谢谢。