How to abort winsock blocking call? - c++

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.

Related

How do I recover when a synchronous call to socket send() gets blocked due to the loss of the other end of the connection?

When my socket connection is terminated normally, then it works fine. But there are cases where the normal termination does not occur and the remote side of the connection simply disappears. When this happens, the sending task gets stuck in send() because the other side has stopped ack'ing the data. My application has a ping request/response going on and so, in another thread, it recognizes that the connection is dead. The question is...what should this other thread do in order to bring the connection to a safe termination. Should it call close()? I see SIGPIPE thrown around when this happens and I just want to make sure I am closing the connection in a safe way. I just don't want it to crash...I don't care about the leftover data. I am using a C++ library that is using synchronous sockets, so moving to async is not an easy option for me.
I avoid this problem by setting setting SIGPIPE to be ignored, and setting all my sockets to non-blocking I/O mode. Once a socket is in non-blocking mode, it will never block inside of send() or recv() -- rather, in any situation where it would normally block, it will instead immediately return -1 and set errno to EWOULDBLOCK instead. Therefore I can never "lose control" of the thread due to bad network conditions.
Of course if you never block, how do you keep your event loop from spinning and using up 100% of a core all the time? The answer is that you can block waiting for I/O inside of a separate call that is designed to do just that, e.g. select() or poll() or similar. These functions are designed to block until any one of a number of sockets becomes ready-to-read (or optionally ready-for-write) or until a pre-specified amount of time elapses, whichever comes first. So by using these, you can have your thread wake up when it needs to wake up and also sleep when there's nothing to do.
Anyway, once you have that (and you've made sure that your code handles short reads, short writes, and -1/EWOULDBLOCK gracefully, as those happen more often in non-blocking mode), you are free to implement your dead-network-detector in any of several ways. You could implement it within your network I/O thread, by keeping track of how long it has been since any data was last sent or received, and by using the timeout argument to select() to cause the blocking function to wake up at the appropriate times based on that. Or you could still use a second thread, but now the second thread has a safe way to wake up the first thread: by calling pipe() or socketpair() you can create a pair of connected file descriptors, and your network I/O thread can select()/poll() on the receiving file descriptor while the other thread holds the sending file descriptor. Then when the other thread wants to wake up the I/O thread, it can send a byte on its file descriptor, or just close() it; either one will cause the network I/O thread to return from select() or poll() and find out that something has happened on its receiving-file-descriptor, which gives it the opportunity to react by exiting (or taking whatever action is appropriate).
I use this technique in almost all of my network programming, and I find it works very well to achieve network behavior that is both reliable and CPU-efficient.
I had a lot of SIGPIPE in my application. Those are not really important: they just tells you that a Pipe (here a SOCKET) is no more available.
I do then, in my main function
signal(SIGPIPE, SIG_IGN);
Another option is to use MSG_NOSIGNAL flag for send, e.g. send(..., MSG_NOSIGNAL);. In that case SIGPIPE is not sent, the call returns -1 and errno == EPIPE.

How could a recv() call block when epoll has signalled activity?

My application is libevent-like, using epoll (in level-triggered mode) to detect I/O activity and invoke callbacks to handle it.
I have recently discovered that my TCP/IP sockets are blocking, which was an accident, but still I wouldn't expect a recv() call to block on an FD which was reported by epoll as having read activity pending. Even if there were an error on the socket, surely recv() would return and tell me about it.
What am I misunderstanding about this?
What sort of network condition could lead to recv() blocking in such a scenario?
From the Linux select man-page:
Under Linux, select() may report a socket file descriptor as "ready
for reading", while nevertheless a subsequent read blocks. This
could for example happen when data has arrived but upon examination
has wrong checksum and is discarded. There may be other
circumstances in which a file descriptor is spuriously reported as
ready. Thus it may be safer to use O_NONBLOCK on sockets that should
not block.
(yeah, I know epoll() is not the same as select(), but I suspect the same underlying conditions apply to both)
I think if you really want to avoid blocking, the only safe way to accomplish that is to set your socket to non-blocking mode.
If you use Epoll to poll for EPOLLIN event, then a recv call after that should return immediately. Furthermore, I hope you are making use of non blocking sockets. In case you want to look for errors, then you can look for EPOLLERR events. In case the socket gets closed after epoll signals, then recv should fail. Code snippet of your epoll_wait, epoll_ctl and socket creation will be helpful in debugging the problem.

Boost.asio, async_read and socket kind

I have a client/server application that is trying to read. When reading from the client, it is done asynchronously. It seems that async_read on the client side is failing.
I think that my client is trying to async_read before the server does the corresponding async_write (not completely sure). So my questions here are conceptual:
can I async_read before the corresponding async_write to the socket on the server side has been done?
I am not sure (cannot try right now), but seems that the kind of socket (blocking/non-blocking) changes the behavior of 1.
In case I want to use non-blocking sockets, how can I async_read when I know there is data available? Is the bytes_readable or similar what I am looking for?
Thank you very much. I would appreciate confirmation on my 3 questions, since I have been trying many things for a while and I have little time to try further experiments.
can I async_read before the corresponding async_write to the socket on the server side has been done?
Yes.
I am not sure (cannot try right now), but seems that the kind of socket (blocking/non-blocking) changes the behavior of 1.
Quite possibly, but you shouldn't put the socket into non-blocking mode. Asynchronous I/O is a third I/O model, nothing to do with non-blocking mode.
In case I want to use non-blocking sockets, how can I async_read when I know there is data available?
This is a contradiction in terms. Asynchronous I/O starts the operation and provides a rendezvous when it finishes. The operation itself remains blocking, but not to the async caller. If you want to use non-blocking sockets you should not be also attempting to use asynchronous I/O.

Winsock - Best way to read, write, send, and receive from sockets

What is the best way to read and write from multiple client sockets on a single thread? I've heard that select() is oldschool and there are better options available. Is the best option currently to use one of WSAAsyncSelect, WSAEventSelect?
Also, what is the difference between WSARecv() and recv(), and WSASend() and send()? Are the WSA versions the most modern way to send and recv data through winsock?
If your single thread is also implementing a GUI then WSAAsyncSelect is designed for this purpose: You get your socket notifications through messages in the Windows queue that your GUI thread must service anyway.
If your single thread is dedicated to the sockets and does not need a message loop, then WSAEventSelect might be more convenient, and a little faster.

cpp unix multithread socket blocking and non-blocking. What is blocking?

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.