I am writing a small 3 servers and 1 client program. the 2 servers send tcp messages and the last one sends upd datagrams using winsock2.
I am wondering if i can make simulanious recvfrom() by using threads (OpenMP or boost::threads) so that 2 threads listen from the same socket on the same port at the same time.
I am using VC++ 2010 on windows7.
Thank you for your help.
Yes, sockets are thread-safe, however you have to be careful. One common pattern (when using blocking IO) is to have one thread receiving data on a socket and another thread sending data on the same socket. Having multiple threads receiving data from a socket is usually fine for UDP socket, but doesn't make much sense for TCP sockets most of the time. There is a warning in the documentation for WSARecv:
WSARecv should not be called on the same socket simultaneously from
different threads, because it can result in an unpredictable buffer
order.
But this usually isn't of any concern if you are using UDP and the protocol is stateless.
Also note that the WSAEINPROGRESS error code mainly applies to Winsock 1.1:
WSAEINPROGRESS: A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.
And the description of WSAEINPROGRESS further states:
Operation now in progress.
A blocking operation is currently executing. Windows Sockets only allows a single blocking operation—per- task or thread—to be outstanding, and if any other function call is made (whether or not it references that or any other socket) the function fails with the WSAEINPROGRESS error.
Note that this talks about a single blocking operation per-task or thread.
Furthermore there is an additional warning in the documentation for WSARecv:
Issuing another blocking Winsock call inside an APC that interrupted an ongoing blocking Winsock call on the same thread will lead to undefined behavior, and must never be attempted by Winsock clients.
But apart from those warnings you should be fine.
Update: to add some external references:
alt.winsock.programming: Is socket thread-safe?
and Winsock Programmer’s FAQ: Is Winsock thread-safe?
Winsock allows only one blocking IO call on a socket. More than one blocking call from different thread would end up with "WSAEINPROGRESS" error. http://msdn.microsoft.com/en-us/library/windows/desktop/ms740668%28v=vs.85%29.aspx#WSAEINPROGRESS.
If you want to make concurrent IO request you could try using asynchronous IO or overlapped IO (in windows parlance). But I guess you would want concurrent processing of data more than concurrent reading data. In which case you could have one thread issuing IO requests and others for processing.
Related
I am implementing a J1939 socket handler on top of Boost::ASIO and canary. My previous application had a socket to listen for devices and the each device discovered would also have a socket. Each socket would use the same interface (In this case can0). From my understanding of SocketCan and J1939 this is the correct approach. As each socket can have filters applied to only get messages from the device its listening for.
In my current application I have tested async_read on two sockets with two threads executing io_context.run(). From the logs this seems to be perfectly fine. I am guessing that this is because the kernel checks against the filters on each socket before passing the data on. However with async_write I am a lot more uncertain about thread safety.
Given that all the sockets have the same interface (can0) would the sockets need to share a strand? Or is a strand in each socket handler enough? Or is there is there some synchronization in the kernel that means writing to the CAN-bus is thread safe.
Yes there is synchronization in the kernel. The same happens for example with TCP sockets. They also share a single network interface (like eth0). The linux network subsystem makes sure, that different sockets (used by different threads or even processes) can share one interface without colliding. You only need synchronization if you access one socket from several threads simultaneously.
I am using IOCP in my client, but I find it more convenient to use a blocking call when connecting to the server. So is there any problem in using the blocking WSAConnect() instead of the non-blocking ConnectEx() when working with IOCP?
Yes, it's perfectly fine.
a call to WSAConnect will block the thread until a connection has being created/ an error has occured. then, you can do asynchronous IO and get notification about completed packets with your application IOCP. the IOCP will not give any packets regarding WSAConnect.
Another point is that IOCP works exculsivly with Overlapped IO. if your function does not consume any memory location of OVERLAPPED struct (like WSAConnect), you can be sure that IOCP will not deal with that API call. even if OVERLAPPED supplied, that doesn't mean that the action is asynchronous and will be published in the IOCP.
you might want to take a look at Boost.Asio for C++ and libuv for C. the code then will be portable as well (and less buggish). another intresting platform is microsoft Casablanca, which is cross platform, but in my experince the performance is catastrophic.
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.
I'm working on a server in c++ that will connect to a multitude of clients via UDP. I've decided that a thread pool would be best to handle incoming datagrams from a given socket.
My question is, then, would it be best in terms of scalability to allow each worker thread to make a call to sendto? Should they do so on the same socket or would a different one be preferable? All the traffic will go through a single port.
From what I've ready, it seems that the calls to recvfrom and sendto are atomic and I already have a dedicated thread to listen to the socket (currently nonblocking and uses calls to select to figure out whether a socket is ready to be read from).
If I were to go on my own accord, I would probably utilize a different socket to send and use multiple threads to do so (assuming all actions were valid).
Not sure how helpful this will be, but this is the general idea:
There is no advantage to using multiple UDP sockets for multiple threads so as long they are non-blocking, and using a single bound UDP socket better maps to your stated requirements. That's part of the fun of implementing stateless, datagram-oriented protocols.
Does this address/confirm your question(s)?
I use Winsock 2 in C++, and wonder how to make my server stop reading from the client connection. The reading thread gets blocked in recv() and I have no idea how to abort it. One way to do this is use non-blocking sockets with select(), but this thread has to wait before checking the new select().
What is the proper way to stop reading the socket?
To abort the blocking call to recv(), you can close the socket with closesocket() from another thread. Even if it's a bit ugly, it should work.
You can try to shutdown() the socket too (I never tested that).
If your program has other things to do besides working with socket I/O, you should not block in the first place.
You claim your thread must wait, but that's just a reflection of your program's current design. You should redesign it so it works with some form of non-blocking sockets. Every networking problem can be addressed using non-blocking sockets.
Since you're using Winsock, you have many alternatives here, not just select(). select() is a good choice only if your application must run on many platforms and you are unable to use the superior (but mutually incompatible) alternatives available on every modern platform.