Прблема с сокетами.
От: Requiem  
Дата: 22.02.07 20:53
Оценка:
При вызове метода 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'а прошу помочь.
Заранее благодарен.
Just think...
Re: Прблема с сокетами.
От: Morpheus_  
Дата: 23.02.07 10:53
Оценка:
Здравствуйте, 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>>
Re[2]: Прблема с сокетами.
От: Requiem  
Дата: 23.02.07 11:33
Оценка:
Здравствуйте, 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?
Just think...
Re[2]: Прблема с сокетами.
От: Requiem  
Дата: 23.02.07 11:38
Оценка:
Здравствуйте, Morpheus_

метод Shutdown уже использую, добавил после написания основного сообщения, решил одну из многочисленных проблем, но не появление данного exception'а.

В любом случае спасибо за помощь.
Just think...
Re[3]: Прблема с сокетами.
От: Morpheus_  
Дата: 23.02.07 15:14
Оценка:
Здравствуйте, 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>>
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.