System.Stream, System.Socket: Partial reads & writes?
- Dominant language
- C#
- Stars
- 18.3k
- Forks
- 5.6k
- PR merge metrics
- PR metrics pending
Description
A common pattern with sockets is to set them to be Non-Blocking (`fcntl` with the `O_NONBLOCK` flag). In this mode, if a read or write is attempted and the full buffer size requested cannot be satisfied (a `read`/`recv` when fewer bytes are buffer, ready to be received, or a `write`/`send` when the available output buffer space cannot accommodate the full buffer provided), then the operation returns a successful response, indicating how many bytes were _actually_ processed, and `errno` is set to `EWOULDBLOCK`.
This allows code to transfer as many bytes as it can without blocking the thread and without it being treated as an error state.
Currently, as far as I can tell, there is no way to express this in .NET with the BCL. The `Socket` implementations assume and require that the sockets be blocking. In the `Socket` code, if you supply a non-blocking socket, then a partial operation translates to a `SocketException` with `SocketErrorCode == SocketError.WouldBlock`, and the number of bytes that were actually processed is lost. In the `Stream` code, there is no `Write` family method that has a return type other than `void`; the API is fundamentally built around writes _always_ fully completing.
I note that there was previously some discussion of partial write support specifically in #48826. The discussion there provided a specific rationale for partial write support: The client is expecting there to be more data to write very soon, and wants to avoid a separate `send` call for the remaining partial buffer right now, which could result in an extra TCP frame that is inefficiently conveying little data.
I feel like, more generally, this mode of operation is a core part of the way sockets and, on UNIX systems, file descriptors in general work, and should be reflected in the API.
Contributor guide
Assessment
This issue has not been assessed yet.