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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 23.11.2011, 02:55   #1
DDorgNev
Новичок
Джуниор
 
Регистрация: 13.02.2010
Сообщений: 1
По умолчанию "Мертвое" соединение в ActiveConnections

Здравствуйте.
Вот мой код, который ПОЧТИ абсолютно нормально работает.
ПОЧТИ, потому, что при не нормальном разрыве сети (отключение питание на машине клиента, порыв сетевого кабеля, отказ хаба-роутера и т.д.) когда сервер НЕ получает события Disconnect от клиента и, соответственно считает клиента подключенным, после повторного подключения клиента к серверу в процедуре таймера опроса клиентов (TForm1.TimerClientTimer) на строке
Код:
    // определяем адрес, кто на этом сокете...
    Address := Server.Socket.Connections[i].RemoteAddress;
возникает критическая ошибка List index of bound.
Я понимаю, что при обрыве и повторном соединении клиента список соединений сервера содержит 2 "активных" коннекта.
Один "мертвый", т.е. не получивший события Disconnect и второй, который получился при соединении клиента после исправления ситуации с потерей связи и теперь он актуальный. Даже если я ставлю эту ситуацию в try-except(try-finally) "мертвый" коннект из списка ни куда не девается.
Вопрос:
КАК от этого "мертвяка" избавиться?
КАК его удалить из списка Server.Socket.ActiveConnections?

Сервер:
Код:

type
  TPacket = record
    Code : integer;
    iValue : integer;
    aValue : array[0..500] of char;
  end;
.......

procedure TForm1.FormCreate(Sender: TObject);
begin
  try
    Server := TServerSocket.Create(self);
    Server.OnClientConnect    := Server_ClientConnect;
    Server.OnClientDisconnect := Server_ClientDisConnect;
    Server.OnClientRead       := Server_ClientRead;
    Server.OnClientError      := Server_Error;
  except
    ...
  end;
end;

procedure TForm1.Server_Error(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  Socket.Close;
  ErrorCode:=0;
end;

procedure TForm1.Server_ClientConnect(Sender: TObject; Socket: TCustomWinSocket);
begin

  // если таймер не запущен, запускаем...
  if not self.TimerClient.Enabled then begin
    self.TimerClient.Enabled := true;
  end;

end;

procedure TForm1.Server_ClientDisConnect(Sender: TObject; Socket: TCustomWinSocket); 
begin

  // активных коннектов нет, таймер останавливаем...
  if Server.Socket.ActiveConnections = 0 then
    self.TimerClient.Enabled := false;

end;

procedure TForm1.Server_ClientRead(Sender: TObject; Socket: TCustomWinSocket);
var
  Packet:TPacket;
begin
  
  Socket.ReceiveBuf(Packet, SizeOf(Tpacket));

  case Packet.Code of
.....
  end;
end;


procedure TForm1.TimerClientTimer(Sender: TObject);
var
  i : integer;
  Address : string;
  sSocket: TCustomWinSocket;
  Packet:TPacket;
begin

  self.TimerClient.Enabled := false;

  // пройтись по всем активным соединениям...
  y := Server.Socket.ActiveConnections;

  for i:=0 to y-1 do begin
    // определяем адрес, кто на этом сокете...
    Address := Server.Socket.Connections[i].RemoteAddress;
    // получаем сам сокет...
    sSocket := Server.Socket.Connections[i];
    if sSocket <> nil then begin
      // формируем запрос к клиенту...
      ZeroMemory(@Packet, Sizeof(TPacket));
      ...
      // ... и посылаем его...
      sSocket.SendBuf(Packet, Sizeof(TPacket));
    end;
    // теперь ожидаем ответ от клиента 50 милисекунд
  end;

  // запуск таймера
  self.TimerClient.Enabled := true;

end;
Client:
Код:
procedure TForm1.FormCreate(Sender: TObject);
begin

  self.qtty := 0;

  Client              := TClientSocket.Create(self);
  Client.Port         := 5555;
  Client.Address      := IP_Adress;
  Client.OnError      := Client_Error;
  Client.OnConnect    := Client_Connect;
  Client.OnDisconnect := Client_Disconnect;
  Client.OnRead       := Client_Read;

end;

procedure TForm1.Client_Connect(Sender: TObject; Socket: TCustomWinSocket);
begin

  InitConnect := false;
  Timer1.Enabled:=false;
  SendMessage(Socket, INIT, StrToInt(sLogin), Pchar(sPass));

end;

procedure TForm1.Client_Disconnect(Sender: TObject; Socket: TCustomWinSocket);
begin

end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Client.Close;
end;

procedure TForm1.Client_Error(Sender: TObject; Socket: TCustomWinSocket;
  ErrorEvent: TErrorEvent; var ErrorCode: Integer);
begin
  ErrorCode:=0;
end;

procedure TForm1.SendMessage(Socket: TCustomWinSocket; Code, Value:integer; Other:string);
var
  Packet:TPacket;
begin
  ZeroMemory(@Packet, Sizeof(TPacket));
  ...
  Socket.SendBuf(Packet, Sizeof(TPacket));
end;

procedure TForm1.Timer1Timer(Sender: TObject);
begin

  self.Timer1.Enabled := false;
  inc(self.qtty);
  Client.Close;
  sleep(1000);
  Application.ProcessMessages;
  Client.Open;
  self.Timer1.Enabled := true;

end;
DDorgNev вне форума Ответить с цитированием
Ответ


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

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как обойти "преобразование типа из "string" в "float" невозможно" lexluter1988 Помощь студентам 1 07.08.2010 12:23
"ОКРВВЕРХ", "ОКР", "ЕСЛИ". Как бы их связать. Каравай Microsoft Office Excel 13 17.02.2010 09:53
при вводе на листе "магазин"- код товара появлялось "описание" товара из "склада" с "продажной ценой" aleksei78 Microsoft Office Excel 13 25.08.2009 12:04