I have to write simple client-server application that uses Unix datagram socket. Client may send information to server on the request from the server or he may receive information from server on the request from himself.
I have an idea that one thread will be waiting for user input that determines what request we want to send to the server, and the other thread will just wait for message on the socket from the server, if it is the message we requested it will write it to standard output, if it is the server request thread would write what server requested. I would use mutex so the two threads won't write at the same time to the same socket.
My question is, how the sockets will behave if one thread will read from some socket and at the same time other thread will be sending data using the same socket, is it safe? Or should I use mutex for this situation also?
Kernel structures are normally built in a thread-safe way; and sockets are no exception. If you should be worried about anything, it isn't the safety of using sockets and threads but the logic of your program.
Also, I'd like to mention that stream sockets are full-duplex, meaning read/write are guaranteed happen simultaneously safely, how can this be happen? Kernel locks for you or makes sure you can do both send and receive at the same time.
For the full-duplex argument:
http://www.kernel.org/doc/man-pages/online/pages/man2/socket.2.html
For the kernel structures are thread safe:
I couldn't find you a link to support this, but I am 99% sure about it.
P.S When in doubt, testing the thing might help
EDIT:
Please, if something of what I said is wrong, comment about it before down voting.
EDIT.2 :
Here you can find that ths POSIX standard specifies that all of its functions have to be thread-safe except a list defined in section 2.9.1
http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html
In linux and windows, the send() and recv() calls (typically used for TCP but I think may be used with UDP as well) may return early without having sent the full amount of data you wanted to send. This will lead to threading issues as your messages will get split up.
I find it's easiest to just wrap the recv() and send() functions with the following properties:
and then just use the wrappers in all the places I would have used send/recv.
Here's the code for the wrappers ( feel free to change the error handling):
//linux (must change SOCKET types to int)
//#include <sys/socket.h>
//windows
//#include <Winsock2.h>
//#include <ws2tcpip.h>
//blocks until the full amount of bytes requested are read
//thread safe
//throws exception on error
void recv_bytes(SOCKET socket, char* buf, int len, int flags){
static std::mutex mtx;
mtx.lock();
int bytes_received = 0;
while (bytes_received != len){
int bytes = recv(socket, buf + bytes_received, len - bytes_received, flags);
//error check
if (bytes == 0){
throw std::exception("Network Exception");
}
bytes_received += bytes;
}
mtx.unlock();
}
//blocks until the full amount of bytes requested are sent
//thread safe
//throws exception on error
void send_bytes(SOCKET socket, char* buf, int len, int flags){
static std::mutex mtx;
mtx.lock();
int bytes_sent = 0;
while (bytes_sent != len){
int bytes_s0 = send(socket, buf, len, flags);
if (bytes_sent == SOCKET_ERROR) {
mtx.unlock();
throw std::exception("Network Exception");
}
bytes_sent += bytes_s0;
}
mtx.unlock();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With