Based on this article, calling WSASend() or WSARecv() from multiple threads is not safe. However, is it safe to call WSASend() and WSARecv() at the same time from two threads?
It is always safe to read from a socket in one thread while simultaneously writing to the same socket in another thread. Separate kernel buffers are involved. Regardless of whether you are using blocking, non-blocking, overlapped, or IOCP I/O logic.
What is not safe is simultaneously reading from the same socket in multiple threads, or simultaneously writing to the same socket in multiple threads. That requires synchronization between the threads so their transmitted/received data do not overlap each other.
Related
I'm very new in the network programming, i writed an IOCP network for Windows with c++, but i have a big contradiction;
many threads can send to same socket, so i used a lock before WSASend because i read about WSASend is not thread-safe, my question is, a thread calls WSASend and while send operation is in progress, if another thread calls WSASend again, what do i need to do?
Should i call WSASend for the second call, or do i need to add a queue and when its completed, send the cache?
What is the best performance tricks for iocp?
I have read that you are not supposed to use send() on a blocking socket from multiple threads, but I do not know why! And if I want to use send() from multiple threads, is there anything I can do to allow it?
I am using Windows.
The fundamental reason is that synchronous I/O functions use the handle object (sockets are implemented as handles) to keep track of whether the I/O is complete or not.
The result is that if you try to send() to the same socket from multiple threads simultaneously, send() is liable to (a) hang or (b) exit before the I/O is actually complete, with catastrophic results.
You can use a critical section to prevent the sends from overlapping, or have a designated thread that reads data to send from a queue.
Note that this only applies if the sends are to the same socket. Sending to different sockets simultaneously is fine.
Alright so basically I have 3 threads.
Each one of them use a function which inside uses the send() on a specific socket (let's call it S).
Here's a small design:
How would I synchronize the S socket in such a way so that send() will be called one after another in a queue instead of the threads accessing the socket all at the same time?
First, why not have an actual queue of data to be sent, and a dedicated IO thread popping items off of it and writing to the socket?
Then, if you are using regular blocking socket semantics, you can just write to the same socket from all three threads concurrently - the kernel will provide required locking at the system call level.
At my multithread application I using AF_UNIX type of socket. Seems by default its blocking. The question is whats mean by "blocking"? Is it block the thread when it execute the ::recv or ::send calls or all threads on the application (like fgets do)?
If it block all threads/whole application, I guess need to use non-blocking sockets? If so, please, give the good example of how to set up AF_UNIX non-blocking socket and when need to set non-blocking mode (and how). How to ::recv ? thanks.
Blocking calls make the thread wait for the operation to complete. Use them when your thread cannot continue before the operation has completed, for example due to the data dependency on the input being received.
Non-blocking calls return as soon as the information is buffered for transmission, or the read operation is initiated. Use them when there are no data dependencies.
In general, blocking always means "blocks the current thread", not "block all threads in my process.
It only blocks the thread that makes the recv call.
I have a project where Thread A calls Accept(...) on some socket, then it passes it to another thread, which does receive on the socket and then closes the socket.
The object on which accept was called is never closed in Thread A. Is that safe?
What happens to that object in Thread A?
A socket is not an object - it's just a number (or conceivably a pointer). If you pass an integer from one thread to another, there are no issues - the same with sockets. This assumes you are asking about OS level sockets, and not some socket class that you or a framework you are using have implemented, and that you only access the socket from one of the threads, which seems to be the case.
Yes it will close. But this will not assure that the unused socket is immediately available for garbage collection (reference in ThreadA)
Sockets & Threads, a few golden rule...
Socket objects are not tread safe, make sure that you're using some sort of lock/mutex to access this resource (think synchronization)
Socket access (like any other I/O) is a blocking operation, this can create a LOT of contention (and waste a lot of CPU cycles) in case of multi-threaded access
ALWAYS explicitly close sockets (server or client), just to be double sure & not surprise yourself l8r
if you're continuously going to read data from a socket & other threads are going to consume this data, USE a thread safe data structure (a concurrent queue) for other threads to consume from. so one thread just reads data from the socket & makes it available on the queue, from where the other threads can work on the data