При вызове метода Close() столкнулся со следущей проблемой:
На сервере есть следущий код, предназначенный для принятия запроса от клиента с последующей обработкой:
internal Socket wSocket;
private NetworkStream sNS;
private BinaryReader sReader;
private BinaryWriter sWriter;
...
public void RunClient()
{
try
{
...
while (Accept)
{
string message = sReader.ReadString();
string command = message.Substring(0, 6);
switch (command)
{
case "000002":
Disconnect(false);
break;
...
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
Так же есть функция для отключения:
// Если вызов функции происходит со стороны сервера, то who = true,
// Если со стороные клиента, то who = false.
public void Disconnect(bool who)
{
Accept = false;
if (who)
sWriter.Write("000002");
sWriter.Close();
sReader.Close();
sNS.Close();
wSocket.Close();
}
При вызове данной функции клиентом все работает замечательно, а вот при попытке вызова данной функции со стороны сервера (допустим при нажатии кнопки) появляется следущий Exception:
System.IO.IOException: Unable to read data from the transport connection: Программа на вашем хост-компьютере разорвала установленное подключение. ---> System.Net.Sockets.SocketException: Программа на вашем хост-компьютере разорвала установленное подключение
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.IO.Stream.ReadByte()
at System.IO.BinaryReader.ReadByte()
at System.IO.BinaryReader.Read7BitEncodedInt()
at System.IO.BinaryReader.ReadString()
at Server.Client.RunClient() in C:\Documents and Settings\...\...\Server\Form1.cs:line 359
Line 359: string message = sReader.ReadString();
Собственно я прикрасно понимаю, что программа в момент вызова Close(), ожидает прихода с сервера очередной команы и именно из за этого возникает Exception. Возможно требуется вызов доп метода перед вызовом Close(), только вот не как не могу найти его, если кто знает/имеет идеи как избавиться от данного Exception'а прошу помочь.
Заранее благодарен.
Здравствуйте, Requiem, Вы писали:
R>System.IO.IOException: Unable to read data from the transport connection: Программа на вашем хост-компьютере разорвала установленное подключение. ---> System.Net.Sockets.SocketException: Программа на вашем хост-компьютере разорвала установленное подключение
R>Собственно я прикрасно понимаю, что программа в момент вызова Close(), ожидает прихода с сервера очередной команы и именно из за этого возникает Exception. Возможно требуется вызов доп метода перед вызовом Close(), только вот не как не могу найти его, если кто знает/имеет идеи как избавиться от данного Exception'а прошу помочь.
Не очень понятно в чем заключается проблема, этот exception появляется при попытке чтения из сокета соединение с которым уже закрыто.
Возможно здесь речь идет о том что сервер сразу после отправки пакета закрывает соединение, а клиент не успевает его принять? Если так, то у сокета есть метод Shutdown, его нужно вызывать перед Close, тогда к моменту вызова Close все отправленные до этого данные будут гарантировано доставлены до закрытия соединения
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Здравствуйте, Morpheus_, Вы писали:
M_>Не очень понятно в чем заключается проблема, этот exception появляется при попытке чтения из сокета соединение с которым уже закрыто.
M_>Возможно здесь речь идет о том что сервер сразу после отправки пакета закрывает соединение, а клиент не успевает его принять? Если так, то у сокета есть метод Shutdown, его нужно вызывать перед Close, тогда к моменту вызова Close все отправленные до этого данные будут гарантировано доставлены до закрытия соединения
Данная функция может быть вызвана в двух случаях:
1. если клиент отсылает на сервер команду завершить работу (000002):
while (Accept)
{
string message = sReader.ReadString();
string command = message.Substring(0, 6);
switch (command)
{
case "000002":
Disconnect(false); /* false, указывает что данная команда пришла с клиента, соответственно не требуется
посылать команду на отключение клиенту*/
break;
...
}
}
тоесть происходит вызов данной функции, в процессе которой флаг Accept устанавливается в положение false, поток завершается и все прекрасно работает (на сервере).
2. воторой случай вызов данной функции происходит допустим при обработке нажатия на кнопку (на сервере).
В данном случаае вызов функции осуществляется следующим образом:
Disconnect(true); // true, указывает что необходимо отправить клиенту комманду на отключение.
Во время вызова данной функции сервер ожидает прихода очередной (какой либо) команды от клиента:
string message = sReader.ReadString();
Проблема заключается в том, что при вызове Close() прочесть что либо из сокета соед. с которым уже закрыто с помощью BinaryReader уже не возможно и соответственно появляется данный exception сообщающий что "Программа на вашем хост-компьютере разорвала установленное подключение."
Я думаю что нечего страшного в этом нету, но мне крайне не нравится сам факт появления данного исключения. Соответственно вопрос стоит в том, что возможно пред методом Close() требуется вызвать еще какой нибудь метод, который прекратит ожидание чтения с помощью BinaryReader?
Здравствуйте, Requiem, Вы писали:
R>2. воторой случай вызов данной функции происходит допустим при обработке нажатия на кнопку (на сервере).
R>В данном случаае вызов функции осуществляется следующим образом:
R>Disconnect(true); // true, указывает что необходимо отправить клиенту комманду на отключение.
R>Во время вызова данной функции сервер ожидает прихода очередной (какой либо) команды от клиента:
R>string message = sReader.ReadString();
R>Проблема заключается в том, что при вызове Close() прочесть что либо из сокета соед. с которым уже закрыто с помощью BinaryReader уже не возможно и соответственно появляется данный exception сообщающий что "Программа на вашем хост-компьютере разорвала установленное подключение."
после вызова Close делать чтолибо с сокетом уже нельзя, правда во втором фреймворке появились какието методы для того чтобы заново открыть сокет, но я этим не пользовался.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>