4

The flag MSG_WAITALL can be used for recv, which requests recv to block until the full request is satisfied. That means recv will not return until as much data as requested (specified by the argument len) has been received, unless an error occurs or the connection has been closed.

Why doesn't such a flag apply to send too? I think it would be very useful for sending (send doesn't return until ALL the bytes the caller wants to send has been handed to TCP send buffer)

xiaokaoy
  • 1,608
  • 3
  • 15
  • 27

1 Answers1

3

It would be redundant. You can always put the socket into blocking mode, if it isn't already, in which case send() blocks until all the data has been transferred.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    And by *transferred*, you mean *queued to the kernel's send queue*. – selbie May 29 '17 at 19:21
  • 1
    Will a blocking socket really send all the data? `man` says that `send` returns amount of bytes sent which implies something else can happen. Additionally, in this case it's not clear what's the purpose of function `sendall` that languages like Ruby and Python add to their socket modules. – u354356007 May 30 '17 at 12:57
  • @Vovanrock2002 The data will be transfered from your buffer to somewhere else. There is no guarantee (and can't be, actually) that the receiving side will actually "receive" your data instead of throwing it away. – Joker_vD Jun 05 '17 at 20:00
  • 1
    This answer can't be correct. By the same reasoning, MSG_WAITALL isn't need at all - blocking recv() could return when all data requested is read. – pfalcon Feb 06 '19 at 11:27
  • 1
    @pfalcon No. `recv()` does not have this behaviour without the MSG_WAITALL flag. – user207421 Feb 06 '19 at 17:42
  • @Vovanrock2002 Yes,mitmwill transfer all the data. Posix requires it. The return value is for non-blocking mode. – user207421 Feb 06 '19 at 17:43
  • "No. recv() does not have this behaviour without the MSG_WAITALL flag." - True. send() also doesn't have that behavior without the MSG_WAITALL flag. And as MSG_WAITALL is not available for send(), send() doesn't have that behavior at all. In other words, send() may end with short write at any time, and requires looping on the app side. – pfalcon Feb 06 '19 at 21:05
  • saving a syscall is NOT redundant - the sole reason that the sendfile(2) function EXISTS is to save syscalls.. which are relatively expensive (if you're in userland code, anyway) - and now with SPECTRE/MELTDOWN mitigations, syscalls are more expensive than ever – hanshenrik Mar 26 '19 at 18:18
  • @hanshenrik I didn't say anything about 'saving a syscall' being redundant'. I said the *flag* would be redundant, and it is. Don't put words into my mouth. – user207421 Dec 12 '19 at 11:29
  • @phafcon You are mistaken. Posix requires the behaviour I have described. If it didn't, `send()` *would* have a MSG_WAITALL flag and the question wouldn't have been asked. – user207421 Dec 12 '19 at 11:33
  • @user207421 if send() had a MSG_WAITALL, you could send a blocking packet on a non-blocking socket with a single syscall, but because it doesn't have that, you have to do 2-3 syscalls: 1: first change it to blocking 2: issue send() 3 (optional): set it back to non-blocking. saving 1-2 syscalls would not be redundant. – hanshenrik Dec 12 '19 at 11:36
  • @hanshenrik In other words if `send()` had a MSG_WAITALL you could force a non-blocking socket to block without even realizing it. There is nothing desirable about that. The correct solution for the three-stage scenario you describe is to use `select()` to wait for writeability. – user207421 Mar 22 '21 at 00:14