Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

simultaneously read and write on the same socket in C or C++

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?

like image 722
Jimm Avatar asked Oct 23 '12 00:10

Jimm


People also ask

Can you read and write from a socket at the same time?

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.

Can socket programming be done in C?

Socket Programming in C/C++ What is socket programming? Socket programming is a way of connecting two nodes on a network to communicate with each other. One socket(node) listens on a particular port at an IP, while the other socket reaches out to the other to form a connection.

Can multiple threads use the same socket?

No two threads can use the same Socket because of the Synchronize sections. So they're never mutating it at the same time. However you're not free of deadlocks, and you may very well end up with many threads waiting for the sync on the same Socket, when others are available.

What are C sockets?

A socket is a generalized interprocess communication channel. Like a pipe, a socket is represented as a file descriptor. Unlike pipes sockets support communication between unrelated processes, and even between processes running on different machines that communicate over a network.


2 Answers

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 and write 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 or poll or async operations... 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 statement 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, but ultimately what you've asked for is easily achieved atop OS-provided BSD sockets or their Windows bastardisation.

like image 111
Tony Delroy Avatar answered Sep 23 '22 11:09

Tony Delroy


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.

like image 23
Zack Yezek Avatar answered Sep 23 '22 11:09

Zack Yezek