所以我有一个TCP
服务器,它等待特定端口连接客户端。
如果有一个客户端连接,我用tcp::socket
构造一个asio::io_service
对象,然后我接受该套接字。例如:
void Gateway::server(boost::asio::io_service& io_service, unsigned short port) {
tcp::acceptor a(io_service, tcp::endpoint(tcp::v4(), port));
bool UARTToWiFiGatewayStarted = false;
for (;;) {
tcp::socket sock(io_service);
a.accept(sock);
std::thread(startWiFiToUARTSession, std::move(sock)).detach();
if(false == UARTToWiFiGatewayStarted) {
//std::thread(startUARTToWifiSession, std::move(sock2)).detach();
UARTToWiFiGatewayStarted = true;
}
}
}
现在我想在至少两个线程上使用这个套接字的功能,一个线程将从套接字(read_some(...)
)读取(阻塞),另一个线程需要写入(阻塞)数据使用那个插座。
我尝试使用相同的tcp::socket
对象构建两个asio::io_service
个对象,但这些对象无法正常工作。
有什么想法吗?
答案 0 :(得分:2)
socket
对象旨在获取本机套接字的所有权,并提供RAII语义来管理本机套接字。因此,单个socket
对象应该引用离散的本机套接字。否则,底层套接字的状态可能会意外更改。
虽然socket
文档指定在单个共享socket
上进行并发调用是不安全的,但revision history会记录此规则的例外情况。从Asio 1.4.0 / Boost 1.37开始,如果OS支持,同步在socket
对象上同时进行的读取,写入,接受和连接操作都是线程安全的:< / p>
Asio 1.4.0 / Boost 1.37
- ...
- 同步读取,写入,接受和连接操作现在是线程安全的(这意味着现在允许它在单个套接字上执行并发同步操作,如果操作系统支持的话)。
- ...
在这种情况下,如果操作系统支持,从一个线程中的套接字同步读取,并在另一个线程中同时写入同一个套接字是线程安全的。