Как правильно обрабатывать разъединение Socket Client в списке Socket / Thread? - PullRequest
0 голосов
/ 05 июля 2018

Я довольно новичок в попытке программировать с помощью сокетов. У меня есть класс, чьи переменные экземпляра включают в себя клиентский сокет и поток клиента, имя которого называется clientInfo. Я создал список clientInfos для отслеживания подключений, идущих на сервер, где мне успешно удалось заставить несколько клиентов отправлять сообщения друг другу.

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

Поток clientInfo находится в бесконечном цикле, чтобы всегда получать входящие данные, как показано в коде ниже. У меня была идея, что если я получу исключение от сервера, пытающегося получить данные от отключенного клиента, все, что мне нужно сделать, это удалить клиента из списка, вызвавшего исключение, верно?

Я бы перебрал клиентов, чтобы точно определить, в каком месте списка появляется ошибка, отправив сообщение пульса. Если отправка не удалась, у меня теперь есть точное местоположение проблемного сокета, а затем я бы закрыл их сокет, прервал поток и удалил clientInfo из списка, верно? Я надеюсь, что у меня есть правильная идея для этой логики. Тем не менее, когда я это сделаю, мне все еще предстоит по-настоящему решить исключение, и поэтому (я думаю) код стреляет сам по себе, закрывая все другие соединения. Честно говоря, я не знаю, что делать, чтобы решить эту проблему.

Существует также неблагоприятный фактор отправки пакетов на каждый сокет в списке, где возникает исключение ObjectDisposedException, если я закрываю, отменяю и удаляю сокет из списка. Есть ли способ полностью удалить элемент из списка, как если бы он никогда не был добавлен? Я предположил, что removeAt (i) сделал бы это, но я ошибаюсь.

Я прочитал много ответов, утверждая, что лучший способ обработать отключение клиентов - это использовать socket.close () и list.removeAt (i). Моя желаемая цель состоит в том, чтобы, даже если 98 из 100 клиентов неожиданно потеряли соединение, я хотел бы, чтобы оставшиеся два клиента все еще могли отправлять друг другу пакеты через сервер. Я на правильном пути или мой подход совершенно неверен?

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

        }
...