Search code examples
c#tcpstreamtimeouttcpclient

When to use TcpClient.ReceiveTimeout vs. NetworkStream.ReadTimeout?


When programming a TCP server I would like to set the timeout period for reading the request from the client:

var tcpClient = tcpListener.AcceptTcpClient();
var networkStream = tcpListener.GetStream();

tcpClient.ReceiveTimeout = 10000;
networkStream.ReadTimeout = 10000;

See the last two lines. Which one should I prefer? Are they equal in terms of effectivity or in which way do they differ?


Solution

  • Which one should I prefer?

    Both the former and the latter will set their internal Socket to the received timeout. That same socket will bubble from from the TcpClient to the NetworkStream created, so I'd go with the former.

    Are they equal in terms of effectivity or in which way to they differ?

    It's a good thing we can look at the source code. This is TcpClient.ReceiveTimeout:

    public int ReceiveTimeout 
    {
        get 
        {
            return numericOption(SocketOptionLevel.Socket,
                                 SocketOptionName.ReceiveTimeout);
        }
        set 
        {
            Client.SetSocketOption(SocketOptionLevel.Socket,
                              SocketOptionName.ReceiveTimeout, value);
        }
    }
    

    Which sets the underling client socket's receive timeout (Client is of type Socket). And then passed to the NetworkStream:

    public NetworkStream GetStream() 
    {
        // Shortened for brevity
        if (m_DataStream==null)
        {
            m_DataStream = new NetworkStream(Client, true);
        }
        return m_DataStream;
    }
    

    And when the NetworkStream looks for the timeout, it looks inside the Socket:

    public override int ReadTimeout 
    { 
        get 
        {
            int timeout = (int)m_StreamSocket.GetSocketOption(SocketOptionLevel.Socket,
                                                              SocketOptionName.ReceiveTimeout);
            if (timeout == 0) 
            {
                return -1;
            }
        }
        return timeout;
    }