Search code examples
c#socketsstreamtcpclient

Does TcpClient write method guarantees the data are delivered to server?


I have a separate thread on both client and server that are reading/writing data to/from a socket.

I am using synchronous TcpClient im (as suggested in documention): https://msdn.microsoft.com/cs-cz/library/system.net.sockets.tcpclient%28v=vs.110%29.aspx

When connection is closed .Read()/.Write() throws an exception. Does it mean that when .Write() method does not throw the data were delivered correctly to the other party or do I need to implement custom ACK logic?

I read documentation for both Socket and TcpClient class and none of them describe this case.


Solution

  • All that a returning send() call means (or any wrapper you use, like Socket or TcpClient) on a streaming, blocking internet socket is that the bytes are placed in the sending machine's buffer.

    MSDN Socket.Send():

    A successful completion of the Send method means that the underlying system has had room to buffer your data for a network send.

    And:

    The successful completion of a send does not indicate that the data was successfully delivered.

    For .NET, the underlying implementation is WinSock2, documentation: send():

    The successful completion of a send function does not indicate that the data was successfully delivered and received to the recipient. This function only indicates the data was successfully sent.

    A call to send() returning does not mean the data was successfully delivered to the other side and read by the consuming application.

    When data is not acknowledged in time, or when the other party sends a RST, the Socket (or whichever wrapper) will become in a faulted state, making the next send() or recv() fail.

    So in order to answer your question:

    Does it mean that when .Write() method does not throw the data were delivered correctly to the other party or do I need to implement custom ACK logic?

    No, it doesn't, and yes, you should - if it's important to your application that it knows another party has read that particular message.

    This would for example be the case if a server-sent message indicates a state change of some sort on the client, which the client must apply to remain in sync. If the client doesn't acknowledge that message, the server cannot know for certain that the client has an up-to-date state.

    In that case you could alter your protocol so that certain messages have a required response which the receiver must return. Do note that implementing an application protocol is surprisingly easy to do wrong. If you're inclined, you could implement having various protocol-dictated message flows using a state machine, for both the server and the client.

    Of course there are other solutions to that problem, such as giving each state a unique identifier, which is verified with the server before attempting any operation involving that state, triggering the retry of the earlier failed synchronization.

    See also How to check the capacity of a TCP send buffer to ensure data delivery, Finding out if a message over tcp was delivered, C socket: does send wait for recv to end?