•  

ГлавнаяIndyЧастые вопросы по Indy → IDTCPServer каким способом идентифицировать подключение (поток) к серверу ?

Создано: 17.05.2014 1:13:42 · Исправлено: 17.05.2014 1:13:42 · Прочтений: 1812

Использую indy. Использую компонент IDTCPServer. Задача следующая: Есть к приложению подключаются клиенты, авторизируются и ожидают некоторого события. Как только событие происходит, сервер отвечает одному (или нескольким) клиентам. Никак не могу сообразить каким способом я могу идентифицировать подключение (поток) к серверу ??? Чтобы ответить не всем, а только выбранным клиентам.
Вот как можно запомнить клиентов:
type
  TSimpleClient = class
    DNS, Name: string;
    ListLink: Integer;
    Thread: Pointer;
  end;
var
  Client: TSimpleClient;
...
type
  TfmMain = class(TForm)
...
    FClientsHost: TList; // Список подключенных клиентов
...
  end;
...
procedure TfmMain.FormCreate(Sender: TObject);
begin
...
  FClientsHost:= TList.Create;
  { Remove all bindings that currently exist }
  tcpServer.Bindings.Clear;
  { Create a new binding }
  with tcpServer.Bindings.Add do
    { Assign that bindings port to our new port }
    Port := FPort; //tcpServer.DefaultPort;
  tcpServer.Active := true;
end;            // FormCreate
procedure TfmMain.tcpServerConnect(AThread: TIdPeerThread);
begin
  // Добавить
  { Create a client object }
  Client:= TSimpleClient.Create;
  { Assign its default values }
  Client.DNS:= AThread.Connection.LocalName;
  Client.Name:= Logging In;
  Client.ListLink:= FClientsHost.Count;
  { Assign the thread to it for ease in finding }
  Client.Thread:= AThread;
  { Assign it to the thread so we can identify it later }
  AThread.Data:= Client;
  { Add it to the clients list }
  FClientsHost.Add(Client);
  Client:= nil;
end;            // tcpServerConnect
Принять сообщение:
procedure TfmMain.tcpServerExecute(AThread: TIdPeerThread);
var
  RestMsg: string;
begin
  try
    RestMsg:= AThread.Connection.ReadLn(EOL); { EOL из модуля IdGlobal.pas }
  except
    Exit;
  end;
...
end;            // tcpServerExecute
Отправить сообщения:
procedure TfmMain.PostMsg(const sMsg: string);
var
  Count: Integer;
  List: TList;
begin
  List := tcpServer.Threads.LockList;
  try
    for Count := 0 to List.Count - 1 do
    try
      TIdPeerThread(List.Items[Count]).Connection.WriteLn(sMsg);
    except
      TIdPeerThread(List.Items[Count]).Stop;
    end;
  finally
    tcpServer.Threads.UnlockList;
  end;
end;            // PostMsg
Отправку мы делали всем, но у вас в списке FClientsHost все клиенты.
Мне кажется, что такое сделать нельзя. Дело в том, что есть такая вещь как таймаут, то есть если Ваш сервер не будет отвечать, то клиенты через некоторое время просто отвалится, а обратно инициировать соединение сервер просто физически не сможет. Вам придется либо передавать библию, либо заставлять клиентов с некоторой периодичностью опрашивать сервер на предмет наступления таких обновлений.