I have a asynchronous TCP/IP client using asio. When the connection is lost, my handle function of async_read recieve an error. So I'm informed that a connection is lost.
Now, I'm refactoring some legacy codes implementing a synchronous TCP/IP client where the abstract interface enforces this sequence: a synchronous write, then a synchronous read.
Doing that with asio is fairly easy, but I would like to know asynchronously if the connection is lost.
Is there a more elegant way than:
Option A:
Add a thread that checks if the socket is still alive (by trying to read... but how can I be sure that the read doesn't steal data from my synchronous read ? See Boost asio ip tcp iostream Error Detection)
Option B:
Use async_read instead and and emulate a synchronous read
I would imagine that the synchronous operation would fail just like the asynchronous one would. It might be more disruptive when the synchronous one fails though, since the timeout could be very long and much more noticeable when everything else has to wait on it.
You might want to look into enabling TCP keep-alives on your socket, and possibly lower the TCP keep alive interval, to detect a lost connection sooner.
Related
I am implementing a simple server, that accepts a single connection and then uses that socket to simultaneously read and write messages from the read and write threads.
What is the safe and easy way to simultaneously read and write from the same socket descriptor in c/c++ on linux?
I dont need to worry about multiple threads read and writing from the same socket as there will be a single dedicated read and single dedicated write thread writing to the socket.
In the above scenario, is any kind of locking required?
Does the above scenario require non blocking socket?
Is there any opensource library, that would help in the above scenario?
In the above scenario, is any kind of locking required?
None.
Does the above scenario require non blocking socket?
The bit you're probably worried about - the read/recv and write/send threads on an established connection - do not need to be non-blocking if you're happy for those threads to sit there waiting to complete. That's normally one of the reasons you'd use threads rather than select, epoll, async operations, or io_uring - keeps the code simpler too.
If the thread accepting new clients is happy to block in the call to accept(), then you're all good there too.
Still, there's one subtle issue with TCP servers you might want to keep in the back of your mind... if your program grows to handle multiple clients and have some periodic housekeeping to do. It's natural and tempting to use a select or epoll call with a timeout to check for readability on the listening socket - which indicates a client connection attempt - then accept the connection. There's a race condition there: the client connection attempt may have dropped between select() and accept(), in which case accept() will block if the listening socket's not non-blocking, and that can prevent a timely return to the select() loop and halt the periodic on-timeout processing until another client connects.
Is there any opensource library, that would help in the above scenario?
There are hundreds of libraries for writing basic servers (and asking for 3rd party lib recommendations is off-topic on SO so I won't get into it), but ultimately what you've asked for is easily achieved atop an OS-provided BSD sockets API or the Windows bastardisation ("winsock").
Sockets are BI-DIRECTIONAL. If you've ever actually dissected an Ethernet or Serial cable or seen the low-level hardware wiring diagram for them, you can actually SEE distinct copper wires for the "TX" (transmit) and "RX" (receive) lines. The software for sending the signals, from the device controller up to most OS APIs for a 'socket', reflects this and it is the key difference between a socket and an ordinary pipe on most systems (e.g. Linux).
To really get the most out of sockets, you need:
1) Async IO support that uses IO Completion Ports, epoll(), or some similar async callback or event system to 'wake up' whenever data comes in on the socket. This then must call your lowest-level 'ReadData' API to read the message off the socket connection.
2) A 2nd API that supports the low-level writes, a 'WriteData' (transmit) that pushes bytes onto the socket and does not depend on anything the 'ReadData' logic needs. Remember, your send and receive are independent even at the hardware level, so don't introduce locking or other synchronization at this level.
3) A pool of Socket IO threads, which blindly do any processing of data that is read from or will be written to a socket.
4) PROTOCOL CALLBACK: A callback object the socket threads have smart pointers to. It handles any PROTOCOL layer- such as parsing your data blob into a real HTTP request- that sits on top of the basic socket connection. Remember, a socket is just a data pipe between computers and data sent over it will often arrive as a series of fragments- the packets. In protocols like UDP the packets aren't even in order. The low-level 'ReadData' and 'WriteData' will callback from their threads into here, because it is where content-aware data processing actually begins.
5) Any callbacks the protocol handler itself needs. For HTTP, you package the raw request buffers into nice objects that you hand off to a real servlet, which should return a nice response object that can be serialized into an HTTP spec-compliant response.
Notice the basic pattern: You have to make the whole system fundamentally async (an 'onion of callbacks') if you wish to take full advantage of bi-directional, async IO over sockets. The only way to read and write simultaneously to the socket is with threads, so you could still synchronize between a 'writer' and 'reader' thread, but I'd only do it if the protocol or other considerations forced my hand. The good news is that you can get great performance with sockets using highly async processing, the bad is that building such a system in a robust way is a serious effort.
You don't have to worry about it. One thread reading and one thread writing will work as you expect. Sockets are full duplex, so you can read while you write and vice-versa. You'd have to worry if you had multiple writers, but this is not the case.
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.
I am implementing a simple server, that accepts a single connection and then uses that socket to simultaneously read and write messages from the read and write threads.
What is the safe and easy way to simultaneously read and write from the same socket descriptor in c/c++ on linux?
I dont need to worry about multiple threads read and writing from the same socket as there will be a single dedicated read and single dedicated write thread writing to the socket.
In the above scenario, is any kind of locking required?
Does the above scenario require non blocking socket?
Is there any opensource library, that would help in the above scenario?
In the above scenario, is any kind of locking required?
None.
Does the above scenario require non blocking socket?
The bit you're probably worried about - the read/recv and write/send threads on an established connection - do not need to be non-blocking if you're happy for those threads to sit there waiting to complete. That's normally one of the reasons you'd use threads rather than select, epoll, async operations, or io_uring - keeps the code simpler too.
If the thread accepting new clients is happy to block in the call to accept(), then you're all good there too.
Still, there's one subtle issue with TCP servers you might want to keep in the back of your mind... if your program grows to handle multiple clients and have some periodic housekeeping to do. It's natural and tempting to use a select or epoll call with a timeout to check for readability on the listening socket - which indicates a client connection attempt - then accept the connection. There's a race condition there: the client connection attempt may have dropped between select() and accept(), in which case accept() will block if the listening socket's not non-blocking, and that can prevent a timely return to the select() loop and halt the periodic on-timeout processing until another client connects.
Is there any opensource library, that would help in the above scenario?
There are hundreds of libraries for writing basic servers (and asking for 3rd party lib recommendations is off-topic on SO so I won't get into it), but ultimately what you've asked for is easily achieved atop an OS-provided BSD sockets API or the Windows bastardisation ("winsock").
Sockets are BI-DIRECTIONAL. If you've ever actually dissected an Ethernet or Serial cable or seen the low-level hardware wiring diagram for them, you can actually SEE distinct copper wires for the "TX" (transmit) and "RX" (receive) lines. The software for sending the signals, from the device controller up to most OS APIs for a 'socket', reflects this and it is the key difference between a socket and an ordinary pipe on most systems (e.g. Linux).
To really get the most out of sockets, you need:
1) Async IO support that uses IO Completion Ports, epoll(), or some similar async callback or event system to 'wake up' whenever data comes in on the socket. This then must call your lowest-level 'ReadData' API to read the message off the socket connection.
2) A 2nd API that supports the low-level writes, a 'WriteData' (transmit) that pushes bytes onto the socket and does not depend on anything the 'ReadData' logic needs. Remember, your send and receive are independent even at the hardware level, so don't introduce locking or other synchronization at this level.
3) A pool of Socket IO threads, which blindly do any processing of data that is read from or will be written to a socket.
4) PROTOCOL CALLBACK: A callback object the socket threads have smart pointers to. It handles any PROTOCOL layer- such as parsing your data blob into a real HTTP request- that sits on top of the basic socket connection. Remember, a socket is just a data pipe between computers and data sent over it will often arrive as a series of fragments- the packets. In protocols like UDP the packets aren't even in order. The low-level 'ReadData' and 'WriteData' will callback from their threads into here, because it is where content-aware data processing actually begins.
5) Any callbacks the protocol handler itself needs. For HTTP, you package the raw request buffers into nice objects that you hand off to a real servlet, which should return a nice response object that can be serialized into an HTTP spec-compliant response.
Notice the basic pattern: You have to make the whole system fundamentally async (an 'onion of callbacks') if you wish to take full advantage of bi-directional, async IO over sockets. The only way to read and write simultaneously to the socket is with threads, so you could still synchronize between a 'writer' and 'reader' thread, but I'd only do it if the protocol or other considerations forced my hand. The good news is that you can get great performance with sockets using highly async processing, the bad is that building such a system in a robust way is a serious effort.
You don't have to worry about it. One thread reading and one thread writing will work as you expect. Sockets are full duplex, so you can read while you write and vice-versa. You'd have to worry if you had multiple writers, but this is not the case.
I have created a linux server using epoll. And I realized that the clients will use udp packets...
I just erased the "listen" part from my code and it seems like working. But I was wondering any hidden issues or problems I might face.
Also, is this a bad idea using epoll for server if clients are sending udp packets?
If the respective thread does not need to do anything else but receive UDP packets, you can as well just block on recvfrom, this will be the exact same effect with one less syscall and less code complexity.
On the other hand, if you need to do other things periodically or with some timely constraints that should not depend on whether packets arrive on the wire, it's better to use epoll anyway, even if it seems overkill.
The big advantage of epoll is that besides being reasonably efficient, it is comfortable and extensible (you can plug in a signalfd, timerfd or eventfd and many other things).
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.