如何正确处理套接字/线程列表中的套接字客户端断开连接?

时间:2018-07-05 05:48:55

标签: c# multithreading sockets socketexception

我在尝试使用Socket编程时还很陌生。我有一个类,其实例变量包括一个名为clientInfo的客户端套接字和客户端线程。我创建了一个clientInfos列表,以跟踪进入服务器的连接,在该服务器中,我已经成功地设法使多个客户端相互发送消息。

            listOfClients.Add(new clientInfo(listen.Accept()));

clientInfo的线程处于无限循环中,始终接收传入的数据,如下面的代码所示。我以前的想法是,如果我从试图从断开连接的客户端接收数据的服务器上收到异常,我要做的就是删除列表中导致异常的客户端,对吗?

我将遍历客户端,通过发送心跳消息来准确找到错误在列表中的哪个位置。如果发送失败,我现在可以找到有问题的套接字的确切位置,然后关闭它们的套接字,中止线程,然后从列表中删除clientInfo,对吗?我希望我对此逻辑有正确的认识。但是,当我这样做时,我仍未真正解决异常,这就是为什么(我认为)代码也通过关闭所有其他连接而步入正轨。老实说,我不知道该怎么办。

还有一个不幸的因素是将数据包发送到列表中的每个套接字,如果我关闭,中止并从列表中删除套接字,则会引发ObjectDisposedException。有没有一种方法可以从列表中完全删除某项,就像从来没有添加过一样?我以为removeAt(i)会这样做,但是我错了。

我已经阅读了许多答案,指出处理客户端断开连接的最佳方法是使用socket.close()和list.removeAt(i)。我期望的目标是,即使100个客户端中有98个意外断开连接,我希望其余两个客户端仍然能够通过服务器相互发送数据包。我是在正确的道路上还是我的方法完全错误?

        byte[] buff;
        int readBytes;

        while (true) {
            try {
                buff = new byte[clientSocket.SendBufferSize];

                readBytes = clientSocket.Receive(buff);
                //This line raises an exception should a client disconnect unexpectedly.


                if (readBytes > 0) {
                    Packet pack = new Packet(buff);
                    handleData(pack);
                }

            }
            catch(SocketException e) {
                Console.WriteLine("A client disconnected!");

                for (int i = 0; i < listOfClients.Count; i++) {
                    try {
                        string message = "This client is alive!";
                        Packet heartbeat = new Packet(Packet.PacketType.Send, "Server");
                        heartbeat.data.Add(message);

                        clientSocket.Send(heartbeat.toByte());
                    }
                    catch (SocketException ex) {
                        Console.WriteLine("Removing " + listOfClients[i].clientEndPointy.Address + ":" + listOfClients[i].clientEndPointy.Port);

                        //listOfClients[i].clientSocket.Disconnect(reuseSocket: true);
                        listOfClients[i].clientSocket.Close();
                        listOfClients[i].clientThread.Abort();
                        listOfClients.RemoveAt(i);
                    }
                }
            }

        }

0 个答案:

没有答案