Is Winsock thread-safe
Is Winsock thread-safe?
Winsock 线程安全吗?
On modern Windows stacks, yes, it is, within limits.
在 现代 Windows 栈上,在一定范围内是这样的。
It is safe, for instance, to have one thread calling send()
and another thread calling recv()
on a single socket.
例如,在单个套接字上有一个线程调用send()
,另一个线程调用recv()
,这样是安全的。
By contrast, it’s a bad idea for two threads to both be calling send()
on a single socket. This is “thread-safe” in the limited sense that your program shouldn’t crash, and you certainly shouldn’t be able to crash the kernel, which is handling these send()
calls. The fact that it is “safe” doesn’t answer key questions about the actual effect of doing this. Which call’s data goes out first on the connection? Does it get interleaved somehow? Don’t do this.
相比之下,两个线程同时在一个套接字上调用 send()
是个坏主意。这在有限的意义上是 “线程安全” 的,即你的程序不会崩溃,当然也不会让处理这些 send()
调用的内核崩溃。事实上,它是 “安全” 的并不能回答一个关键问题:关于这样做的实际效果。哪个调用的数据会在连接上首先发送?是否会以某种方式交错?所以不要这样做。
Instead of multiple threads accessing a single socket, you may want to consider setting up a pair of network I/O queues. Then, give one thread sole ownership of the socket: this thread sends data from one I/O queue and enqueues received data on the other. Then other threads can access the queues (with suitable synchronization).
你可能需要考虑设置一对网络 I/O 队列,而不是多个线程访问单个套接字。然后,让一个线程单独拥有套接字:该线程从一个 I/O 队列发送数据,并将接收到的数据放入另一个队列。然后,其他线程可以访问队列(需要适当的同步)。
Applications that use some kind of non-synchronous socket typically have some I/O queue already. Of particular interest in this case is overlapped I/O or I/O completion ports, because these I/O strategies are also thread-friendly. You can tell Winsock about several OVERLAPPED blocks, and Winsock will finish sending one before it moves on to the next. This means you can keep a chain of these OVERLAPPED blocks, each perhaps added to the chain by a different thread. Each thread can also call WSASend()
on the block they added, making your main loop simpler.
使用某种非同步套接字的应用程序通常已经有了一些 I/O 队列。在这种情况下,重叠 I/O 或 I/O 完成端口尤其值得关注,因为这些 I/O 策略也是线程友好的。你可以告诉 Winsock 多个 OVERLAPPED 块,Winsock 会在移动到下一个块之前完成一个块的发送。这意味着你可以保留一连串的 OVERLAPPED 块,每个块都可能由不同的线程添加到链中。每个线程还可以在它们添加的块上调用 WSASend()
,从而使主循环更简单。
【参考资料】
本文章翻译自
Winsock Programmer’s FAQ: Intermediate Winsock Issues (tangentsoft.com)
本文链接:https://blog.csdn.net/u012028275/article/details/134193922