我在尝试使用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);
}
}
}
}