如何检测telnet客户端何时未正确关闭tcp服务器?

时间:2013-04-22 01:53:13

标签: c# tcplistener

我正在尝试创建一个小型IRC服务器来学习一些新的编程概念(以及其他我没有永远使用过的概念)。第一步是通过TCP连接基本客户端,向服务器发送明文命令。

要监听连接,我有以下代码:

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++;
    }
}

然后在我的NetworkClient课程中,我的Start()方法如下:

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);
        }
    }
}

这在连接telnet客户端时运行良好,但是一旦我关闭我的telnet客户端reader.ReadLineAsync();,就会不断返回null。我会添加一个检查以查看是否line == null,但我不确定这是检测客户端是否已断开连接的正确方法。

更糟糕的是,_socket.Connected一直在返回true,而reader.ReadLineAsync()则“收到”空值。

检测tcp客户端断开连接的正确方法是什么?

1 个答案:

答案 0 :(得分:5)

当正常关闭连接时,TCP / IP套接字上的读取将返回0个字节。 This situation causes ReadLineAsync to return null.所以,是的,您应该检查null并将其视为优雅的套接字闭包。

套接字也可能以其他方式关闭;如果套接字被中止关闭,任何套接字操作都可能抛出异常。如果异常发生在协议的可接受部分(其中close不被视为错误),那么您应该将该异常视为优雅的闭包。

哦,TcpClient.Connected(就像Socket.Connected)几乎没用; it only tells you whether the socket was connected, not whether it is connected。只是假装财产不存在。

最后,有几点说明:

  • 避免使用async void。如果您的方法返回Task,那么您有一个“句柄”来查看它们何时完成(以及它们是否引发了异常)。我的recent MSDN article解释了为什么不推荐async void
  • 最好通过连接定期发送数据,以确定它是否仍然可行。我写了TCP/IP .NET sockets FAQ covers this in more detail