[英]Strange behaviour of either io_context or std::cout in multi-threaded UDP server
我有一個使用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;
}
}
我使用boost::thread
創建了server
函數的 3 個線程,並將其分配給thread_group
:
boost::asio::io_context io_context;
boost::thread_group tg;
boost::thread *t = new boost::thread(server, std::ref(io_context), 8889);
boost::thread *t1 = new boost::thread(server, std::ref(io_context), 8890);
boost::thread *t2 = new boost::thread(server, std::ref(io_context), 11111);
tg.add_thread(t);
tg.add_thread(t1);
tg.add_thread(t2);
tg.join_all();
為了測試服務器,我使用了Packet Sender 。 問題是輸出是... scrambled 。 當在 3 個端口上每秒(或多或少)同時發送一次數據包時,輸出稍微錯位,但是當將數據包頻率增加到每 0.1 秒一次時,輸出變得不可讀,如這兩個圖像所示。 我曾嘗試為每台服務器提供一個單獨的io_context
對象,但輸出頻率高時保持不變。 有什么辦法可以避免這種情況嗎?
合乎邏輯(且正確)的解決方案是在std::cout
上使用互斥。 您知道鎖的適當范圍(在您的情況下,只有一個 UDP 數據包,但std::cout
無法猜測)。
奇特的解決方案是boost.asio.strand
。 你並不需要一個簡單的情況就是這樣,但因為你試圖使用boost.asio.io_context
你應該知道,還有另一個類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;
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.