1 - Is Winsock thread-safe?

The Winsock specification does not mandate that a Winsock implementation be thread-safe, but it does allow an implementor to create a thread-safe version of Winsock.

Bob Quinn says, on this subject:

  • "WinSock, any implementation, is thread safe if the WinSock implementation developer makes it so (it doesn't just happen)."
  • "I don't know of any implementations from Microsoft (or any other vendors) that are not thread safe."
  • "If a WinSock application developer creates a multi-threaded application that shares sockets among the threads, it is that developer's responsibility to synchronize activities between the threads."

By "synchronize activities", I believe Bob means that it may cause problems if, for example, two threads repeatedly call send() on the same socket. There is no guarantee in the Winsock specification about how the data will be interleaved in this situation. Similarly, if one thread calls closesocket() on a socket, it must somehow signal other threads using that socket that the socket is now invalid.

Anecdotal evidence suggests that one thread calling send() and another thread calling recv() on a single socket is safe on recent Microsoft stacks at least.

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).

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.

2 - If two threads in an application call recv() on a socket, will they each get the same data?

No. Winsock does not duplicate data among threads.

Note that if you do call recv() at the same time on a single socket from two different threads, havoc may result. See the previous question for more info.

3 - Is there any way for two threads to be notified when something happens on a socket?

No. If two threads call WSAAsyncSelect() on a single socket, only the thread that made the last call to WSAAsyncSelect() will receive further notification messages. Similarly, if two threads call WSAEventSelect() on a socket, only the event object used in the last call will be signaled when an event occurs on that socket. You also can't call WSAAsyncSelect() on a socket in one thread and WSAEventSelect() on that same socket in another thread, because the calls are mutually exclusive for any single socket. Finally, you cannot reliably call select() on a single socket from two threads and get the same notifications in each, because one thread could clear or cause an event, which would change the events that the other thread sees.

posted on 2009-03-05 13:41  njdragonfly  阅读(621)  评论(0编辑  收藏  举报