在我们的应用程序中,我们使用Boost库(和ASIO进行网络通信)。最近,我们发现如果我们通过同一套接口从不同线程发送数据,我们的客户端应用程序正在接收垃圾数据。从不同线程写入boost :: asio socket
小试,以突出的问题:
#include <stdio.h>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
void send_routine(boost::shared_ptr<boost::asio::ip::tcp::socket> s, char c)
{
std::vector<char> data(15000, c);
data.push_back('\n');
for (int i=0; i<1000; i++)
boost::asio::write(*s, boost::asio::buffer(&data[0], data.size()));
}
int main()
{
using namespace boost::asio;
using namespace boost::asio::ip;
try {
io_service io_service;
io_service::work work(io_service);
const char* host = "localhost";
const char* service_name = "18000";
tcp::resolver resolver(io_service);
tcp::resolver::query query(tcp::v4(), host, service_name);
tcp::resolver::iterator iterator = resolver.resolve(query);
auto socket = boost::shared_ptr<tcp::socket>(new tcp::socket(io_service));
socket->connect(*iterator);
boost::thread t1(send_routine, socket, 'A');
boost::thread t2(send_routine, socket, 'B');
boost::thread t3(send_routine, socket, 'C');
t1.join();
t2.join();
t3.join();
}
catch (std::exception& e) {
printf("FAIL: %s\n", e.what());
}
return 0;
}
所以,我们在这里创建插座,连接到localhost:18000
并启动3个线程将写入套接字。
在不同的终端窗口中,我运行了nc -l -p 18000 | tee out.txt | sort | uniq | wc -l
。我期望3
作为输出,但它会在网络流中返回多于100个“不同的字符串”(因此数据已损坏)。但它适用于小缓冲区大小(例如,如果我们将15000
更改为80
)。
所以,问题是:这是ASIO库的正确行为吗?另一个:如何解决它?我应该在我的send_routine
函数中使用mutex
(还是有另一种解决方案)?
'async_write'不会神奇地让这个问题消失。不同缓冲区的写入仍然需要串行发生,即使它是通过异步IO完成的。 – Chad 2012-07-20 15:46:59
'io_service'应该为你序列化。 – berkus 2014-11-11 17:56:51
async_write由多个async_send组成,没有进一步的线程安全性(我研究了实现)。所以当从不同的线程使用相同的套接字时它不是线程安全的。 – Databyte 2015-06-07 12:22:16