这是我原问题的简化版本。
我有几个线程,它们写入一个boost asio套接字。这似乎非常好地工作,没有问题。
文档说,共享套接字不是线程安全的(在这里,在底部),所以我想知道是否应该使用互斥锁或其他方式保护套接字。
这个问题坚持认为需要保护,但并没有提供如何做到这一点的建议。
所有对我的原始问题的答案都坚称我正在做危险的事情,大多数人敦促我用async_writes或者更复杂的方法替换我的写入操作。然而,我不愿意这样做,因为这会使已经正常工作的代码变得更加复杂,回答者中没有人说服我他们知道自己在说什么——他们似乎读过与我相同的文档,并且只是猜测,就像我一样。
因此,我编写了一个简单的程序来压力测试从两个线程向共享套接字写入。
下面是服务器代码,它只是将从客户端接收到的内容写出。
int main()
{
boost::asio::io_service io_service;
tcp::acceptor acceptor(io_service, tcp::endpoint(tcp::v4(), 3001));
tcp::socket socket(io_service);
acceptor.accept(socket);
for (;;)
{
char mybuffer[1256];
int len = socket.read_some(boost::asio::buffer(mybuffer,1256));
mybuffer[len] = '\0';
std::cout << mybuffer;
std::cout.flush();
}
return 0;
}
这里是客户端,它创建了两个线程,尽可能快地向共享套接字写入数据。
boost::asio::ip::tcp::socket * psocket;
void speaker1()
{
string msg("speaker1: hello, server, how are you running?\n");
for( int k = 0; k < 1000; k++ ) {
boost::asio::write(
*psocket,boost::asio::buffer(msg,msg.length()));
}
}
void speaker2()
{
string msg("speaker2: hello, server, how are you running?\n");
for( int k = 0; k < 1000; k++ ) {
boost::asio::write(
*psocket,boost::asio::buffer(msg,msg.length()));
}
}
int main(int argc, char* argv[])
{
boost::asio::io_service io_service;
// connect to server
tcp::resolver resolver(io_service);
tcp::resolver::query query("localhost", "3001");
tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
tcp::resolver::iterator end;
psocket = new tcp::socket(io_service);
boost::system::error_code error = boost::asio::error::host_not_found;
while (error && endpoint_iterator != end)
{
psocket->close();
psocket->connect(*endpoint_iterator++, error);
}
boost::thread t1( speaker1 );
boost::thread t2( speaker2 );
Sleep(50000);
}
这个方法可行!就我所知,它完美地运行着。客户端不会崩溃,消息也不会混乱。它们通常会交替到达服务器,每个线程一个消息。有时一个线程在另一个之前会收到两个或三个消息,但我认为只要没有混淆并且所有消息都到达了,这并不是问题。
我的结论是:在某种理论意义上,socket可能不是线程安全的,但很难使它失败,所以我不会担心它。