Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Работа с сетью в Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 06.10.2009, 20:52   #1
Антон Ю.Б.
Форумчанин
 
Регистрация: 03.01.2009
Сообщений: 116
По умолчанию Indy. Отправка сообщений клиенту и изменяемый ReadTimeout.

D2007, Indy10. Приложение клиент-сервер. Клиент присылает сообщения примерно раз в полминуты. Сервер нормально работает с таймаутом для сокета соединения в 60*1000. Потребовалось сделать обратную связь. Сделал ожидание начала приема по циклу с малым таймаутом (500 мс) и отсылкой сообщений клиенту (если они есть) на обработке исключения EidReadTimeout в этом ожидании (с ограничением 60*2 тактов цикла). После этого возвращаю таймаут к большому значению (связь по GPRS), читаю остаток посылки от клиента и снова перехожу в режим ожидания/отправки клиенту с маленьким таймаутом. Первая посылка от клиента читается, но примерно через 500 мс (малый таймаут) ожидания второй посылки срабатывает OnDisconnect на сервере.

Не подскажет ли кто, почему оно срабатывает?

Ниже привожу значимые фрагменты кода и кусок лога, отражающий их работу. В тестовом прогоне клиенту ничего не отправлялось (то есть просто была проверка по циклу наличия сообщений).

Код:
procedure TFormMain.IdTCPServerExecute(AContext: TIdContext);
var
  Working: boolean;
  TB:TidBytes;
  i:SmallInt;
  SID:Integer;
begin
  Working:=true;
  Randomize();
  SID:=Random(100)+Random(100);

  while Working do
    begin
      AContext.Connection.Socket.ReadTimeout:=500;
      SetLength(TB,0);
      if not(IdTCPServer.Active)
      then Working:=False
      else WriteToLog(IntToStr(SID)+': '+'Ожидание сообщения от клиента '+AContext.Connection.Socket.Binding.PeerIP);
      i:=0;
      while Working and (I<2*60) and (Length(TB)=0) do
        begin
          try
            AContext.Connection.Socket.ReadBytes(TB,1,false);
            AContext.Connection.Socket.ReadTimeout:=10000;
          except
            on E:EIdReadTimeout do
              begin
                i:=i+1;
                Sleep(10);
                if <есть сообщение для клиента>
                then
                  try
                    AContext.Connection.Socket.WriteLn(<посылка>);
                  except
                    on E:Exception do
                      begin
                        Working:=False;
                        WriteToLog(IntToStr(SID)+': '+'Ошибка отправки посылки клиенту '+AContext.Connection.Socket.Binding.PeerIP);
                      end;
                  end
                else WriteToLog(IntToStr(SID)+': '+'Не обнаружено сообщений для отправки клиенту '+AContext.Connection.Socket.Binding.PeerIP);    
              end;
            on E:Exception do
              begin
                if not(E is EIdReadTimeout) then
                  begin
                    WriteToLog(IntToStr(SID)+': '+'Ошибка ('+E.Message+') чтения кода посылки от клиента '+AContext.Connection.Socket.Binding.PeerIP);
                    Working:=False;
                  end;
              end;
          end;
        end;
      if Length(TB)=0
      then Working:=False
      else WriteToLog(IntToStr(SID)+': '+'Код посылки от клиента '+AContext.Connection.Socket.Binding.PeerIP+' получен за '+IntToStr(i)+' итераций по 500 мс');
      if (not Working)
      then
        begin
          WriteToLog(IntToStr(SID)+': Ошибка начала чтения посылки от клиента '+AContext.Connection.Socket.Binding.PeerIP+' Считано '+IntToStr(Length(TB))+' байт за '+IntToStr(i)+' итераций по '+IntTostr(AContext.Connection.Socket.ReadTimeout)+' мс');
          Working:=False;
        end
      else
      case TB[0] of
        1: <читаем и обрабатываем посылки от клиентов>
     ...
    end;
  if AContext.Connection.Connected
  then
    begin
      WriteToLog(IntToStr(SID)+': '+'Отключаем клиента '+AContext.Connection.Socket.Binding.PeerIP);
      AContext.Connection.Disconnect;
    end;
end;   

procedure TFormMain.IdTCPServerDisconnect(AContext: TIdContext);
begin
  dec(ConnectCount);
  WriteToLog('Отключился клиент: '+AContext.Connection.Socket.Binding.PeerIP);
end;
Код:
18:23:46:511: Подключился клиент: 217.118.95.70
18:23:46:511: 18: Ожидание сообщения от клиента 217.118.95.70
18:23:47:27: 18: Не обнаружено сообщений для отправки клиенту 217.118.95.70
18:23:47:542: 18: Не обнаружено сообщений для отправки клиенту 217.118.95.70
18:23:48:58: 18: Не обнаружено сообщений для отправки клиенту 217.118.95.70
18:23:48:574: 18: Не обнаружено сообщений для отправки клиенту 217.118.95.70
18:23:49:89: 18: Не обнаружено сообщений для отправки клиенту 217.118.95.70
18:23:49:605: 18: Не обнаружено сообщений для отправки клиенту 217.118.95.70
18:23:50:120: 18: Не обнаружено сообщений для отправки клиенту 217.118.95.70
18:23:50:511: 18: Код посылки от клиента 217.118.95.70 получен за 7 итераций по 500 мс
18:23:50:511: 18 Начало приема данных типа 1 от клиента 217.118.95.70
18:23:50:511: 18: Окончание приема данных типа 1 от клиента 217.118.95.70
18:23:50:527: 18: Ожидание сообщения от клиента 217.118.95.70
18:23:51:42: Отключился клиент: 217.118.95.70

Последний раз редактировалось Антон Ю.Б.; 06.10.2009 в 21:17.
Антон Ю.Б. вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Отправка SMS сообщений RUBEY Компоненты Delphi 11 25.06.2011 17:40
Отправка сообщений вконтакте.ру mustang007 Работа с сетью в Delphi 3 28.06.2009 12:53
IdTCPServer отправка сообщений. gusluk Работа с сетью в Delphi 3 08.04.2009 09:43
автоматическая отправка сообщений DeDoK Общие вопросы Delphi 3 16.10.2008 08:50
отправка сообщений Pitbull Работа с сетью в Delphi 6 03.08.2007 17:06