Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can a TCP Socket SendAsync operation complete without transferring all the bytes in a BufferList?

Tags:

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 on EndSend until the Socket 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.

like image 741
Sotirios Delimanolis Avatar asked Jan 04 '17 18:01

Sotirios Delimanolis


1 Answers

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.

like image 56
Ton Plooij Avatar answered Oct 18 '22 03:10

Ton Plooij