Поддержка / Donate
 

WebMoney

Яндекс.Деньги

SMS.Копилка
Деньги@Mail.ru
Rupay
E-gold
PayPal

 

Благодарю за поддержку!

Лента RSS - Новости сайта Новости сайта
Лента RSS - Новости форума Новости форума
Добавить в закладки и поделиться Bookmark and Share

 

Архив исходников

 


Automatic translation

 
English German French
Italian Spanish Portuguese
Greece Japan Chinese
  Korean  

  

 

  Форум  

Delphi FAQ - Часто задаваемые вопросы

| Базы данных | Графика и Игры | Интернет и Сети | Компоненты и Классы | Мультимедиа |
| ОС и Железо | Программа и Интерфейс | Рабочий стол | Синтаксис | Технологии | Файловая система |



Google  
 

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


Попал фидошник в ад. Ему черт говорит:
- Тебе определено 1000 лет наказания, но т. к. я люблю анекдоты, то разрешаю их тебе рассказывать. Пока ты их рассказываешь, этот срок будет вычтен из твоего наказания.
Ну, фидошник начинает травить анекдоты. Год... два... 100 лет... 900 лет прошло, он все рассказывает. Наконец, на 999 году замолкает.
- Все, анекдоты закончились? Ну, давай хоть год тебя помучаю.
- Да погоди ты, сейчас вторую часть офтопик-листа достану!

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

Вообще-то, создать многопотоковый сервер, который ожидает пришедшие сообщения на сокете довольно просто. В 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 - это размер буфера.




Источник - Проект "Delphi World" © Выпуск 2002 - 2004
Автор проекта: Акулов Николай



   Rambler's Top100             Яндекс цитирования