Is it ok to use same socket fd in multiple threads ? (over linux)
It depends on what you expect to happen, but yes you can. If you are reading UDP packets that are each a complete message this can work well. If you are reading data streams from TCP this will probably not work well.
You can have multiple threads accepting incoming connections on a socket and that can work pretty well as each thread gets one connection.
You will run into concurrency problems trying to send() or recv() (SOCK_STREAM) from multiple threads. You should use a critical section or some other means of creating serial access to send() and recv().
One standard thing to do with threads is to have the master listen() & accept(), then pass off the socket to a client thread that sends/receives/processes from that one socket. The client thread is responsible for calling close() or shutdown().
Related
In Haskell, can the same socket be shared between two threads? Essentially, what I am trying to do is create a thread to write to a socket and another to read from the socket.
The read thread would be a loop that constantly wait, monitor and pick up any messages generated by the socket.
Another thread (the write thread) would send code to the socket.
Please advise.
Yes, this is allowed.
I encounter this problem while trying to do TCP tunnelling between two threads.
Thread 1
listen at Port
accept
then add the sock after accept to epoll_ctl
while (1)
epoll_wait
read whatever from Port to remote (tunnelling)
Thread 2
connect to Port
if connected
communicate...
What I actually observe is: while Thread 2 is blocked on connect, Thread 1 has no chance to run epoll_wait and send the connect info to the remote. Thus both threads cannot make progress.
One possible solution is to use parent-child processes instead of multi-threading. But before I switch to that, could it still be done with multi-threading? I think what it is needed here is some kind of interrupt thing than just polling. Right?
Thank you for the insight.
You can add server side socket descriptor into epoll_ctl. But I'm curious that if thread2 blocked on connection, what information you need to send to server? Thanks for your hint.
ALL,
I am looking for a simple example of non-blocking socket connection that will run on Windows.
I tried to Google, but all samples are either for *nix (POSIX) or blocking sockets on Windows.
Looking thru msdn I see that it is easy to make a socket non-blocking and issue a connect(), but then you need some preparation in order to put the socket back.
So, all in all I need something on a non-blocking socket that will connect and then put it back to be blocking.
The read and write operation should be performed on the blocking socket.
The reason for a non-blocking socket is that I need a connection timeout and there is no other way than non-blocking socket. Or is there?
Thank you.
Use ACE socket wrapper facade and apply your Linux knowledge in full.
I have multiple threads which need to send UDP packets to different IP addresses (only to send, nothing needs to be received). Can I reuse the same UDP socket in all the threads?
Yes, I think you can.
As the packets are sent out individually, although the order they are received will be nondeterministic, it is already with UDP.
So sending in multiple threads in the same socket is fine.
Although, if you're doing other stuff with the socket, such as bind(), close(), then you could end up with race conditions, so you might want to be careful.
System calls are supposed to be atomic, so formally it seems fine for UDP. Then kernels have bugs too and you are inviting all sorts of nasty surprises. Why can't you use socket per thread? It's not like with TCP where you need a connection. As an added bonus you'd get a separate send buffer for each descriptor.
I'd like to make sure about the correctness of the way I try to use accept() on a socket.
I know that in Linux it's safe to listen() on a socket, fork() N children and then recv() the packets in all of them without any synchronisation from the user side (the packets get more or less load-balanced between the children). But that's UDP.
Does the same property hold for TCP and listen(), fork(), accept()? Can I just assume that it's ok to accept on a shared socket created by the parent, even when other children do the same? Is POSIX, BSD sockets or any other standard defining it somewhere?
If you fork() and then accept() in your children only one child process is going to call accept() on a connection and then process it. This is pre-forking and the connections won't be shared among the children.
You can do a standard one child per connection scheme by reversing the order and accepting and forking. However both of these techniques are for efficiency, balancing, etc., not for sharing a particular connection.
TCP is different from UDP. It would be inadvisable to do that in TCP as you will almost certainly end up with a mess. A given received message can be spread over one or more packets and it would be more of a pain for multiple process to coordinate than would be to have one child handle the connection.