On 11/06/2020 03:14, Keith Robinson wrote:
I’m sending data from one process to another using a tcp connection. Sender use scatter-gather to send the data using 3 buffers (total just over 2000 bytes). The reader uses 2 separate sync reads to read the data (using the asio free function read()) using a non blocking socket.
If you can, I recommend using asynchronous reads on a blocking socket instead. It's a little less weird that way since there isn't an "error" that isn't an error.
When it goes wrong for me, the second read always returns less data than I requested, along with the error code ‘would_block’. I then loop, performing further reads (using the same buffer as before), eventually (one read, or multiple reads later) the read function returns the remainder of the data, but still with the error code ‘would_block’ set. However, when I check the contents of the buffer, it is not what I expected. I think, but haven’t been able to confirm, that the start of the buffer is not the start of the data.
1. Is it expected that the read() free function, when the socket is non blocking, can return less data than requested, along with the error code ‘would_block’?
Yes, that just means that it has returned as much data as is currently available, and the rest has not yet been received yet. (Thus the error means it cannot return more data without blocking.) It may depend on which transfer-stop function you've specified, though; with blocking sockets (sync or async) you can tell it to not return until it has read all of the data, even if that takes multiple internal read operations, or to return as soon as it has at least some data. I'm not sure if non-blocking sockets behave differently or not in this regard, but it wouldn't surprise me. Non-blocking sockets aren't fashionable these days.
2. If it is expected, does the buffer passed in subsequent reads have to be adjusted to read only the remaining about of data?
The data that was returned from the first read is entirely valid and present in the buffer. It is your responsibility to either copy this elsewhere before your subsequent read, or pass a start-of-buffer pointer in your subsequent read starting at the point just after the already-read data, so that it doesn't get overwritten. Otherwise you will lose data. ASIO will never "repeat" data that has already been read (unless the originating end sends it multiple times, of course).