4

I have a socket which I receive from and send to in a single thread. However, there exists another thread which can periodically use the socket to send data. Currently, I'm using a shared object to lock my Socket.send() operations. Is this lock necessary? If yes, would I need the lock on my receive method as well even though I'm only receiving from one thread?

Eg in Thread1:

//...some code
 while (offset< len)
    {
       currentBytesRead += Client.Receive(buf, offset, len - offset, SocketFlags.None);
    }
//...some more code...
lock (lockObject)
    {
         Client.Send(outputByte);
    }

In Thread2:

    lock (lockObject)
    {
         Client.Send(outputByte);
    }
user2635088
  • 1,598
  • 1
  • 24
  • 43

2 Answers2

5

As stated in documentation of Socket class, instances of this class are thread safe. Because socket represents duplex connection - you can safely send and receive on different threads. You can also send data from multiple threads without locking, but note that the order is not guaranteed in this case (so if you send single logical structure using multiple send operations - you need to lock for them to not distract each other).

Note however that if you react on some data received by sending some data in response - you need to lock the whole receive-send block, and lock sends from another thread.

Evk
  • 98,527
  • 8
  • 141
  • 191
  • 1
    `if you react on some data received by sending some data in response - you need to lock the whole receive-send block, and lock sends from another thread` - So if I receive data in thread A, process it in some way, and based on that processing, send a response back, I need to lock the whole receive-send block? Is that only true if the network host is expecting a certain response? – user2635088 May 26 '16 at 11:54
  • 2
    Yes, because otherwise you might get that Send from another (second) thread in between of your receive and send, and your client would interpret that as response to his original request. And yes, that is true if client expect any response to his original request. You can work around this by marking each request with some unique identifier (guid) and when sending response back - include id of request. Then client can distinguish for which request this response was created. – Evk May 26 '16 at 11:58
1

Sockets are thread-safe, so no locks are needed in your example.

  • So a single socket.send operation is guaranteed to return before the other thread's socket.send? There is no chance of context switches corrupting the data in the buffer? I.e. I have array1 = [0,0] and array2 = [1,1] and I call socket.send(array1) on thread1 and socket.send(array2) on thread2, the receiver is guaranteed to receive array1 and array2 in whole and there's no chance of them receiving a few bytes of array1 and array2 in some random order? – user2635088 May 26 '16 at 11:58
  • Both messages with be sent seperatly with the default delimiter (i think its \r\n) at the end. – Maarten Zeeman May 26 '16 at 12:11
  • 1
    there is no default delimiter. – esskar Jan 18 '19 at 06:57