【问题标题】:c# detect client disconnection from serverc# 检测客户端与服务器断开连接
【发布时间】:2014-10-31 19:48:33
【问题描述】:

我有一个服务器和 2 个 winform 客户端(用于 tictactoegame)。我可以立即检测到客户端断开连接吗?第一个打开的客户端是 player1 套接字,第二个是 player2。一旦两个客户端都连接了,player1 必须单击一个按钮,player2 按钮都被禁用。在 player1 单击按钮后, player2 按钮被启用,而 player1 按钮被禁用......等等

isConnected 方法

public  bool IsConnected(Socket socket)
{
    try
    {
        return !(socket.Poll(1, SelectMode.SelectRead) && socket.Available == 0);
    }
    catch (SocketException) { return false; }
}

服务器代码

public class ServerApp
{
    public Socket serverSocket;

    Socket player1;
    Socket player2;
    ServerGame myGame;

    public ServerApp()
    {
        myGame = new ServerGame();
        serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, 
                                  ProtocolType.Tcp);
        IPEndPoint ipLocal = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8221);
        serverSocket.Bind(ipLocal);
        serverSocket.Listen(4);

        Console.WriteLine("Waiting for clients ...");
        player1 = serverSocket.Accept();
        Console.WriteLine("Player 1 joined");
        player2 = serverSocket.Accept();
        Console.WriteLine("Player 2 joined");

        myGame.InitGame();

        while (true)
        {
            try
            {
                myGame.Display();
                Console.WriteLine();

                myGame.Send(player1, BaseGame.Player.One);
                myGame.Send(player2, BaseGame.Player.Two);

                if (myGame.GetActivePlayer() == BaseGame.Player.One && 
                    myGame.IsConnected(player1)==true)
                {
                    myGame.Receive(player1);                       
                }
                else if(myGame.IsConnected(player1) == true)
                {
                    myGame.Receive(player2);
                }
            }
            catch(Exception e)
            {
                Console.WriteLine(e);
                Thread.Sleep(1000);                    
            }
        }

        Console.WriteLine("Server going down");
        Thread.Sleep(2000);
    }
}

class Program
{
    static void Main(string[] args)
    {
        ServerApp serverApp = new ServerApp();
    }
}

【问题讨论】:

  • 定义“即时”。计算机无法立即字面上做任何事情,就像你或我一样。但是,取决于网络连接,套接字的优雅关闭可能会很快发生。可能会或可能不会快速检测到重置(断开连接),具体取决于其他情况。您应该更具体地说明您的要求。
  • 假设 player1 必须单击一个按钮,然后 player2 按钮被禁用。如果我关闭 player1 ,我如何检测到我关闭了它(它等待 player2 单击按钮但 player2 按钮被禁用)。如果我想关闭 player2,当我单击 player1 时,我会在控制台上收到一条消息(玩家 2 断开连接等)
  • 上面的示例中是否有一行代码导致您出现问题?
  • 是否应该检查player2 是否已连接而不是player1else if(myGame.IsConnected(player1) == true) { myGame.Receive(player2); }
  • @Rufus,不,它没有

标签: c# client-server


【解决方案1】:

被关闭的玩家应该在退出前优雅地关闭套接字。这包括调用Socket.Shutdown(SocketShutdown.Send),然后等待接收操作返回字节数为0(表示远程客户端也已关闭)。

这将确保及时关闭连接。否则,其他未关闭的玩家将无法知道连接已丢失,直到他们尝试发送一些数据。

【讨论】: