How do I detect when a telnet client is improperly closed to a tcp server?

不问归期 提交于 2019-12-25 16:49:10

问题


I am experimenting in creating a small IRC server to learn some new programming concepts (and others I haven't used in forever). The first step is to get a basic client connecting via TCP to send plaintext commands to the server.

To listen for connection I have the following code:

public NetworkClient(Server server, TcpClient socket, int id)
{
    _socket = socket;
    _id = id;
    _server = server;
}

private async void ListenForClients()
{
    int numClients = 0;
    while (IsRunning)
    {
        var tcpClient = await _listener.AcceptTcpClientAsync();
        var netClient = new NetworkClient(this, tcpClient, numClients);
        netClient.Start();
        Console.WriteLine("Client Connected");

        numClients++;
    }
}

Then in my NetworkClient class my Start() method looks like:

public async void Start()
{
    using (var reader = new StreamReader(_socket.GetStream()))
    {
        while (_server.IsRunning)
        {
            var line = await reader.ReadLineAsync();
            Console.WriteLine("Client {0} wrote: {1}", _id, line);
        }
    }
}

This works well while a telnet client is connected, however once I close my telnet client reader.ReadLineAsync(); constantly returns null. I would add a check to see if line == null but I'm not sure that is the correct way to detect if a client has disconnected.

To make matters worse, _socket.Connected is constantly returning true all while nulls are getting "received" by reader.ReadLineAsync().

What is the proper way to detect when tcp clients have been disconnected?


回答1:


A read on a TCP/IP socket will return 0 bytes when the connection has been gracefully closed. This situation causes ReadLineAsync to return null. So, yes, you should check for null and treat it as a graceful socket closure.

Sockets may be closed other ways, too; any socket operation may throw an exception if the socket is abortively closed. If the exception happens at an acceptable part of the protocol (where a close is not considered an error), then you should treat that exception as though it were a graceful closure as well.

Oh, and TcpClient.Connected (like Socket.Connected) is practically useless; it only tells you whether the socket was connected, not whether it is connected. Just pretend that property doesn't exist.

Finally, a couple of notes:

  • Avoid async void. If your methods return Task, then you have a "handle" to see when they complete (and whether they raised exceptions). My recent MSDN article explains why async void is not recommended.
  • It's best to periodically send data over the connection to determine if it is still viable. I wrote a TCP/IP .NET sockets FAQ that covers this in more detail.


来源:https://stackoverflow.com/questions/16138302/how-do-i-detect-when-a-telnet-client-is-improperly-closed-to-a-tcp-server

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!