5

If I have a socket called s, can I do this in different threads:

Thread 1:

send(s, "Hello from Thread 1");

Thread 2:

send(s, "Hello from Thread 2");

Is it guaranteed that these two strings will be placed in the send buffer one after the other (I don't care which one is placed first), or is there a possibility that they could get mixed together?

Note: maybe this question should have been titled: "Is socket send() thread safe" (but I am not really sure what thread safety means).

Tom
  • 1,344
  • 9
  • 27

1 Answers1

2

The answer is no. Generally send() does not guarantee that the data is being sent in one piece. You always need to check the value returned by send() in order to find out how many bytes actually have been sent. If this is less than the size of your buffer (which is not an error), you have to call send() again, appropriatly in a loop, e.g. something like this:

char *msg="Hello from thread 1";
size_t pos;
size_t currentBytes;
size_t BytesToSend=strlen(msg);

for (pos=0 ; pos < BytesToSend ; pos += currentBytes) {
    currentBytes = send(s, msg + pos, BytesToSend - pos, 0);

    if (currentBytes <= 0) {
       // error occurred (-1) or connection has been closed on remote site (0)
       return ...
    }
}

That means that you data may arrive in pieces, and when sending from two threads the data may be mixed together.

See also send() reference, especially

If no error occurs, send returns the total number of bytes sent, which can be less than the number requested to be sent in the len parameter.

sb9
  • 1,082
  • 7
  • 18
  • I thought that a blocking `send()` call will not return until of the data were sent! – Tom Feb 25 '15 at 16:31
  • @Tom a blocking send() will not return until at least some bytes were sent. There's no guarantee it will block until all bytes were sent. See: http://stackoverflow.com/questions/2618736/why-is-it-assumed-that-send-may-return-with-less-than-requested-data-transmitted – Jeremy Friesner Feb 25 '15 at 16:42
  • @Jeremy Friesner How about `WSASend()`, could it only send part of the data? (`WSASend()` in blocking mode and not using Overlapped I/O). – Tom Feb 25 '15 at 17:11
  • I haven't used WSASend() much, so I can only suggest reading its documentation page: https://msdn.microsoft.com/en-us/library/windows/desktop/ms742203(v=vs.85).aspx (particularly the Remarks section) – Jeremy Friesner Feb 25 '15 at 17:47
  • In blocking mode, `send() ` blocks until all the data had been sent or an error occurs. This is guaranteed by Posix. – user207421 Feb 25 '15 at 18:51
  • @EJP So the quoted text that sb9 has showed from the `send()` documentation is probably talking about non-blocking sockets? Also is Winsock API compliant with POSIX? – John Feb 25 '15 at 19:23
  • The quoted text is from the return value section, and in this part the doc doesn't mention blocking or nonblocking. If considering the complete document, it seems that send in a blocking socket won't return before the whole buffer has been sent. The original question did not mention blocking/nonblocking, and when sending I assumed nonblocking. Nevertheless I would not use the same blocking socket from 2 different threads, because oft possible synchronization problems/deadlocks. – sb9 Feb 25 '15 at 19:57
  • @sb9 You are wrong. There is nothing wrong in calling `send()` from different threads. See here: http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid –  Feb 26 '15 at 00:06
  • @mahmoud_t1: that's POSIX. This is Windows. The rules are different. – Harry Johnston Feb 26 '15 at 02:00
  • @Harry Johnston So should a `send()` be enclosed in a critical section to disallow the execution of multiple `send()` at the same time by different threads? – John Feb 26 '15 at 02:31
  • @John: I'm not sure. Personally I would follow the more restrictive rules (which are usually true for Windows but might not apply in this particular situation) and use a critical section; it might not be necessary, but it won't do any harm other than a marginal loss of performance. – Harry Johnston Feb 26 '15 at 02:57
  • @Harry Johnston Sorry, I did not understand what you mean by "the more restrictive rules", you mean simply the use of critical section? – John Feb 26 '15 at 03:16
  • @John: the usual rules for Windows I/O are more restrictive than the Posix socket rules, i.e., they require the use of a critical section. Since I'm not certain which rules apply, I would take the cautious approach and use a critical section. – Harry Johnston Feb 26 '15 at 03:18
  • @mahmoud_t1: I did not write that it won't work, I wrote that I wouldn't do it this way. – sb9 Feb 26 '15 at 06:58
  • @sb9 Actually you were right, there is a problem in `send()`ing from different threads under Windows. –  Feb 26 '15 at 12:41