3

Calls such as send() and sendto() in the Winsock API take a primitive int to dictate the size of their buffer parameters. This obviously places a 32-bit limit on the maximum size buffer that may be sent.

Why is this? Is there a 64-bit Winsock2 API available that might use a more appropriate size type (e.g. size_t)?

On Linux similar calls use the size_t type for defining sizes.

stephen_mugisha
  • 889
  • 1
  • 8
  • 18
rantman
  • 39
  • 4
  • 5
    you want to send more than 4GB in a single call?! – Alnitak Mar 30 '20 at 11:35
  • 1
    FWIW it is not necessarily true that the size of `int` is 4 bytes on all platforms https://stackoverflow.com/questions/589575/what-does-the-c-standard-state-the-size-of-int-long-type-to-be although that is the case on windows using visual studio https://learn.microsoft.com/en-us/cpp/cpp/data-type-ranges?view=vs-2019 – Cory Kramer Mar 30 '20 at 11:35
  • 1
    Presumably because sending a message larger than 2 gigabytes is an uncommon need. – eerorika Mar 30 '20 at 11:36
  • The native `WSASendMsg` function supports large messages. – Hristo Iliev Mar 30 '20 at 11:47
  • 1
    On different non-windows platforms these calls used to use `int` or `unsigned int` as size type, however this has changed. On Windows changing size type would break binary compatibility of the existing applications. – user7860670 Mar 30 '20 at 11:47
  • Just break up the calls, I see no problem. – Fredrik Mar 30 '20 at 11:49
  • 2
    This question seems to come from a missunderstading of how sockets work. Even if you call send() with 1MB the call to recv() on the other end may recieve anything from 1 byte to the full 1MB and may have to call recv() again. When programming socket you have to tell the reciever how much to recieve or use a marker for end. So you see, when sending data, sending them over multiple calls is not a problem. – Fredrik Mar 30 '20 at 11:56
  • I was curious why the Winsock API was never re-worked to use the more generic “size_t” type. Layers above might compute sizeof() various items and then attempt to pass down into a send() call which restricts length to a 32-bit quantity. In a 32-bit to 64-bit upgrade of legacy code, this can create countless warnings about “loss of data” due to casts from a 64-bit size (eg via sizeof() or strlen() or the like) to a 32-bit int (eg with send() or sendto() like calls). – rantman Mar 30 '20 at 12:12
  • TL;DR: Because anyone needing to use such an API is probably doing something wrong anyway :) As for the "countless warnings": there are easy workarounds for that. You don't need to be using those existing APIs - you can make zero-cost inline wrappers, including `sizeof`! – Kuba hasn't forgotten Monica Mar 30 '20 at 16:19
  • @ReinstateMonica - no, it wasn't a question of doing anything "wrong", it was more the point of why the Winsocks API doesn't support 64-bit interfacing. – rantman Mar 30 '20 at 22:50

1 Answers1

2

There is no need for a function with larger size, actually the type could be short and still it won’t be a problem.

Sockets don’t send messages, they just transfer bytes. When you call send() the data may not get received in one chunk at the recv() call. You have to implement logic when receiving bytes to know if you got it all or not and call recv() again if not. So if you wanna send something larger than can be placed in an int? Just make multiple calls to send(). If your recv() code can’t handle that, it’s a bug, because it should.

Fredrik
  • 1,389
  • 1
  • 14
  • 32
  • 2
    Exactly. It's unlikely that `send()` or `sendto()` will send more bytes in one call than can fit in the socket buffer, which is far smaller than 2 GiB. Data transfer size can be limited by a variety of other factors, too. User code calling these functions *must* check how many bytes were actually sent, and be prepared to to use multiple calls to send more than a single byte, unless it doesn't actually care how much of the data is sent. – John Bollinger Mar 30 '20 at 12:23
  • 1
    Yep, the only reason this is different on Linux is that send/recv are *basically* write/read. – ljrk Mar 30 '20 at 12:55
  • @Fredrik - I'm quite aware of how sockets work, but thank you for the refresher :) The question was why the API was never changed to support 64-bit interfacing. The result of this is countless "warning C4267: 'argument': conversion from 'size_t' to '...', possible loss of data" errors when calling in from higher-level layers. – rantman Mar 30 '20 at 22:54