【问题标题】:Close Client Socket on disconnect断开连接时关闭客户端套接字
【发布时间】:2011-02-18 20:47:15
【问题描述】:

我有侦听客户端的服务器应用程序。 让我们的客户端失去互联网连接并失去与服务器的连接。

服务器是否会自动检查客户端何时断开连接?如果不是,我该如何实现?

Main.cs http://pastebin.com/fHYpErz7

ServerSocket.cs:http://pastebin.com/erw4tzdp

Client.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;

namespace jM2
{
    class Client
    {
        private int clientConnectionID;
        private Socket clientSocket;
        private string clientIP;
        private byte[] clientBuffer = new byte[1024];

        public Client(int connectionID, Socket connectionSocket)
        {
            clientConnectionID = connectionID;
            clientSocket = connectionSocket;
            clientIP = connectionSocket.RemoteEndPoint.ToString();
            clientSocket.BeginReceive(clientBuffer, 0, clientBuffer.Length, SocketFlags.None, new AsyncCallback(dataArrival), null);
        }
        public void Disconnect()
        {
            clientSocket.Close();
        }
        private void dataArrival(IAsyncResult iar)
        {
            int bytesReceived = clientSocket.EndReceive(iar);
            clientSocket.BeginReceive(clientBuffer, 0, clientBuffer.Length, SocketFlags.None, new AsyncCallback(dataArrival), null);
        }
    }
}

【问题讨论】:

    标签: c# sockets asynchronous disconnect


    【解决方案1】:

    查看我对这个问题的回答:

    TcpClient.Close doesn't close the connection

    在您尝试发送数据之前,基本上没有人知道连接是否已关闭。如果失败,则关闭连接。

    【讨论】:

    • 基本上在服务器端创建一个 ping 函数来 ping 客户端,如果没有响应,则关闭该客户端套接字。正确的?还有什么是存储客户端套接字的最佳方式?
    • 我建议您不要使用“ping”功能,而是始终假设客户端和服务器已连接。每当发送时发生错误时,您都可以假设它们已断开连接。这听起来很愚蠢,但仔细想想,仅仅因为它们在 5 秒前当您的 ping 功能响起时已连接,并不意味着它们现在在您发送数据时已连接。
    • 我会将您的客户端套接字存储在所有成员或您的处理代码都可以访问的集合中(可能是List<T>)。可能是类级别的属性,但它取决于您的代码的其余部分。
    【解决方案2】:

    根据 Chris Haas 所说,我可能是错的,但是我之前编写了一个 TCP 服务器并在收到 0 字节时检测到关闭的连接。换句话说,在您的 dataArrival 方法中,如果 bytesReceived 为 0,则表示连接已关闭。这似乎通过了相当广泛的测试。

    【讨论】:

      【解决方案3】:

      我推荐一种“投票”或“心跳”消息,as described here

      【讨论】: