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

Previous  Top  Next

    
 

 

Автор: Brian Pedersen

 

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

 

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

 

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

 

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

 

- Добавляем TServerSocket в Вашу основную форму.

- Устанавливаем свойство Servertype в stThreadBlocking

- Создаём новый "unit" (показанный ниже) содержащий поток сервера.

 

 

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

Code:

procedure TfrmMain.fSocketGetThread(Sender: TObject;

ClientSocket: TServerClientWinSocket;

var SocketThread: TServerClientThread);

begin

// Здесь создаём объект TServerThread, который я привожу ниже.

// Новый объект создаётся каждый раз, когда когда установлен канал связи. 

SocketThread := TServerThread.Create( FALSE, ClientSocket );

end;

 

 

 

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

 

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

Code:

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;

 

 

 

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

Code:

if ( not Terminated ) and

  ( not fSocketStream.WaitForData( 1000000 ) ) then

begin

// Обработчик таймаута (т.е. если по истечении 1000000 миллисекунд

// от клиента не пришло запроса

end;

// В сокете есть входящие данные!

 

 

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

Code:

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 - это размер буфера.

©Drkb::03552

Взято из http://forum.sources.ru