Использование компонента TServerSocket.

В Delphi документации по многопотоковому TServerSocket налито довольно много воды, и начинающему программисту сложно понять суть дела. Давайте попытаемся пролить немного света на этот раздел хелпа.

Совместимость: Delphi 3.x (или выше)

Вообще-то, создать многопотоковый сервер, который ожидает пришедшие сообщения на сокете довольно просто. В Delphi для этой цели достаточно использовать компонент TServerSocket.

Давайте рассмотрим структуру работы данного компонента:

- Добавляем TServerSocket в Вашу основную форму.
- Устанавливаем свойство Servertype в stThreadBlocking
- Создаём новый "unit" (показанный ниже) содержащий поток сервера.

Устанавливаем следующий код на OnSocketGetThread


procedure TfrmMain.fSocketGetThread(Sender: TObject;  
  ClientSocket: TServerClientWinSocket;  
  var SocketThread: TServerClientThread);  
begin  
  // Здесь создаём объект TServerThread, который я привожу ниже.  
  // Новый объект создаётся каждый раз, когда когда установлен канал связи.   
  SocketThread := TServerThread.Create( FALSE, ClientSocket );  
end;   

TServerThread - это объект, который я создаю самостоятельно. Объект наследуется от TServerClientThread и содержит код, который обычно читает и пишет данные из/в сокет.

Созданный "unit", содержит следующий код:


unit serverthread;  
  
interface  
  
uses  
  windows, scktcomp, SysUtils, Classes, Forms;  
  
type  
  EServerThread = class( Exception );  
  // serverthread это потомок TServerClientThread  
  TServerThread = class( TServerClientThread )  
    private  
      fSocketStream : TWinSocketStream;  
    public  
      procedure ClientExecute; override;  
      // ClientExecute отменяет  
      // TServerClientThread.ClientExecute  
      // и содержит код, который  
      // выполняется при старте потока  
  end;  
  
implementation  
  
procedure TServerThread.ClientExecute;  
begin  
  inherited FreeOnTerminate := TRUE;  
  try  
    fSocketStream := TWinSocketStream.Create( ClientSocket,  
                                              100000 );  
    // 100000 - это таймаут в миллисекундах.  
    try  
      while ( not Terminated ) and ( ClientSocket.Connected ) do  
      try  
        // В это место обычно помещается код,  
        // ожидающий входных данных, читающий из сокета или пишущий в него  
        // Пример, приведённый ниже, показывает, что можно добавить в данную  
        // секцию программы.  
      except on e:exception do  
        begin  
          // Если произошла ошибка, то закрываем сокет и выходим  
          ClientSocket.Close;  
          Terminate;  
        end;  
      end;  
    finally  
      fSocketStream.Free;  
    end;  
  except on e:exception do  
    begin  
      // Если произошла ошибка, то закрываем сокет и выходим  
      ClientSocket.Close;  
      Terminate;  
    end;  
  end;  
end;   

Когда связь установлена, потоку необходимо ожидать входящих данных(запроса от клиента). Для этого можно использовать следующий код:


if ( not Terminated ) and  
   ( not fSocketStream.WaitForData( 1000000 ) ) then  
begin  
  // Обработчик таймаута (т.е. если по истечении 1000000 миллисекунд  
  // от клиента не пришло запроса  
end;  
// В сокете есть входящие данные!   

Для чтения данных, Вам понадобится создать буфер для хранения полученных данных. Обычно буфер - это PByteArray или массив символов. В этом примере я обозвал буфер как fRequest который является массивом символов. Кроме того я ожидаю фиксированное количество байт. Массив имеет постоянный размер REQUESTSIZE.


var  
  ac, readlen : integer;  
begin  
  FillChar( fRequest, REQUESTSIZE, 0 );  
  ac := 0;  
  repeat  
    readlen := fSocketStream.Read( fRequest[ac],  
                                   1024 );  
    // считываем блоки по 1024 байт, до тех пор, пока буфер  
    // не заполнится  
    ac := ac+readlen;  
  until ( readlen = 0 ) or ( ac = REQUESTSIZE );  
end;   

Если readlen равно 0, значит больше нет входящих данных. Функция Чтения завершается через 100000 миллисекунд после запуска в TWinSocketStream.Create(). Если Вы не знаете сколько времени нужно ожидать запроса от клиента, то чем меньше будет таймаут, тем лучше. В большинстве случаев максимальный таймаут не должен превышать 30 секунд.

При посылке ответа, Вы должны знать, в каком режиме работает клиент. Многие клиенты ожидают только один пакет ответа, другие ожидают несколько пакетов. В этом примере, я подразумеваю клиента, который ожидает только один пакет, так что я должен послать мои данные назад в одном блоке:


fSocketStream.WriteBuffer( fRep, fReplySize );   

fRep это буфер, содержащий ответ на запрос клиента, и fReplySize - это размер буфера.
Теги:
TServerSocket
Добавлено: 30 Июля 2018 20:29:50 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...