Я пытаюсь закодировать связь клиент-сервер. Пока мне удается подключиться в первом потоке. Второй поток читает сокет, а третий проверяет, нет ли неожиданного disconection от клиента.System.ObjectDisposedException в сокете и когда закрывать потоки
Моя проблема в том, что я получил исключение System.ObjectDisposedException, когда я пытаюсь прочитать сокет. Если я продолжу работу программы (игнорируя исключение), то такое же исключение произойдет, когда я проверю, все еще подключен сокет.
Сервер представляет собой класс со следующими полями:
static class Server
{
static ArrayList readList = new ArrayList();
static ArrayList acceptList = new ArrayList();
static public Thread thread1 = new Thread(new ThreadStart(SocketConnector));
static Thread thread2 = new Thread(new ThreadStart(SocketListener));
static Thread thread3 = new Thread(new ThreadStart(SocketClose));
static Thread thread4 = new Thread(new ParameterizedThreadStart(SocketWriter));
ReadList используется в считывающем сокете нити (последний образец кода в этом сообщении) acceptList содержит результаты Socket.Accept(). Вот как acceptList заполнен.
static void SocketConnector()
{
while (true)
{
sock.Listen(25);
actif = sock.Accept();
if (actif != null)
{
lock (acceptList)
{
acceptList.Add(actif);
Console.WriteLine("IT WORKS");
// that writeline appeared when i try to connect with the client.
}
actif = null;
}
}
Теперь вот как я проверить, если не было никакого неожиданного отключения от клиента:
static void SocketClose()
{
while (true)
{
for (int i = 0; i < acceptList.Count; ++i)
{
if (((Socket)acceptList[i]).Poll(25, SelectMode.SelectRead) && ((Socket)acceptList[i]).Available == 0)
{
lock (acceptList)
{
((Socket)acceptList[i]).Close();
Console.WriteLine("Client " + ((Socket)acceptList[i]).GetHashCode() + " déconnecté");
acceptList.Remove((Socket)acceptList[i]);
i--;
}
}
}
Thread.Sleep(5);
}
И последняя часть кода я должен показать, если, как я прочитал мое гнездо.
static void SocketListener()
{
while (true)
{
readList.Clear();
lock (acceptList)
{
for (int i = 0; i < acceptList.Count; i++)
{
readList.Add((Socket)acceptList[i]);
}
}
if (readList.Count > 0)
{
Socket.Select(readList, null, null, 1000);
for (int i = 0; i < readList.Count; i++)
{
if (((Socket)readList[i]).Available > 0)
{
while (((Socket)readList[i]).Available > 0)
{
Console.WriteLine("Debut Deserialisation");
// get the underlying socket for the TcpClient
TcpClient client = new TcpClient();
client.Client = (Socket)readList[i];
NetworkStream ns = client.GetStream();
BinaryReader reader = new BinaryReader(ns);
Message received = new Message();
Console.WriteLine(received.msg);
Console.WriteLine(received.user);
Console.WriteLine(received.targetChatroom);
// Deserialisation
int length = reader.ReadInt32();
byte[] msgArray = reader.ReadBytes(length);
received.msg = Encoding.UTF8.GetString(msgArray);
length = reader.ReadInt32();
msgArray = reader.ReadBytes(length);
received.user = Encoding.UTF8.GetString(msgArray);
length = reader.ReadInt32();
msgArray = reader.ReadBytes(length);
received.targetChatroom = Encoding.UTF8.GetString(msgArray);
ns.Close();
}
}
}
}
}
я понял, что, возможно, мой сокет был закрыт по линии ns.Close(), и это вызывает ошибку. С ns.Close() я просто попытался закрыть созданный мной поток, чтобы получить данные из сокета, а не закрыть сам сокет. Я попытался удалить эту строку ns.Close(), и ObjectDisposedException больше не появляется! Однако теперь я получил исключение OutOfMemoryException на линии:
в потоке для чтения. Я считаю, что это исключение вызвано тем, что поток не закрыт.
EDIT: Исключение OutOfMemoryException происходит из кода клиента. Проблема решена здесь.
Обнаружение разъединения работает и десериализация.
Мой вопрос: когда следует закрыть этот поток ???
Много кода, но все еще не завершено. Неясно, на каком потоке (ей) это выполняется, и 'new Thread (новый ThreadStart (SocketClose));' не похож на отличный инструмент.Ваша резьба для чтения должна взаимодействовать при остановке и закрытии. –
@ Хенк Холтерман Вы правы. Я редактировал, чтобы показать, какой образец кода принадлежит тому потоку. Нить «SocketClose» - это поток, который проверяет, все еще подключен сокет, если другой хост не отправляет вам пакет, когда он отключается (например, потому что он отключен несправедливо). Возможно, имя не очень хорошо выбрано. – Csi