On Mono 3.12, I'm using Socket.SendAsync(SocketAsyncEventArgs)
with a TCP Stream Socket
to implement a request-based streaming protocol. I'm using SocketAsyncEventArgs.BufferList
to set multiple buffers of data.
In the documentation for Socket
and SocketAsyncEventArgs
, I can't find any mention of whether the SocketAsyncEventArgs.Completed
can be raised without all bytes being sent when BufferList
is used, leaving the impression that we have to validate against SocketAsyncEventArgs.BytesTransferred
.
On the other hand, Socket.BeginSend
makes that guarantee
When your application calls
BeginSend
, the system will use a separate thread to execute the specified callback method, and will block onEndSend
until theSocket
sends the number of bytes requested or throws an exception.
What guarantees does the specification make about the number of bytes transferred when using SendAsync
with a SocketAsyncEventArgs.BufferList
?
Assume that the event was completed with SocketError.Success
.
What guarantees does the specification make about the number of bytes transferred when using SendAsync with a SocketAsyncEventArgs.BufferList
?
To start with, the event can be raised on errors in which case you can assume that not all bytes have been transferred. For this you need to test the SocketAsyncEventArgs.SocketError for SocketError.Success. Also, if you refer to 'specification' I assume you mean the (Microsoft) Windows Sockets documentation (since you link to this for the SendAsync and other descriptions).
In order too make out what the documentation says or implies for the number of transferred bytes when the Completed event is called in case of success, we have to make a few steps. The first step is to see if SendAsync uses overlapped I/O. That question is answered in the Overlapped Input / Output documentation. Implementation for this mechanism is mandatory for underlying transport providers and hence it is the only overlapped I/O mechanism that is guaranteed to be available for Windows Sockets. As such, SendAsync is guaranteed to use a socket with the WSA_FLAG_OVERLAPPED attribute.
Note that inspection of the SendAsync reference implementation shows that SendAsync is indeed using WSASend with overlapped I/O, but that’s merely an observation.
The second step is to determine what overlapped I/O tells us about the signalling of the completed event related the amount of transferred bytes. This situation is described in several places, for example at this Overlapped I/I and Event Objects page: ‘indication will be provided when send buffers have been consumed’. A little more detail is given in the remarks section for the [WSASend] function: ‘A completion indication will occur, invoking the completion of a routine or setting of an event object, when the buffer(s) have been consumed by the transport’.
This still leaves some room for the exact interpretation of this phrase. Basically it says that the data was accepted and confirmed by an underlying transport mechanism out of the socket scope. This does not necessarily mean it has arrived at the remote endpoint protocol layer, this would depend on the communication protocol. For a TCP streaming socket I would infer that it indicates that the data has arrived at the remote endpoint.
The conclusion here is that the documentation guarantees (for a non-error situation) that the SendAsync completed event is raised only at the point when all bytes have been transferred.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With