Использование компонента TServerSocket.
Автор: Brian Pedersen
В 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 - это размер буфера.
Тестирование параллельного программного обеспечения представляет собой более
сложную задачу по сравнению с тестированием последовательной программы. Программист
должен знать о подводных камнях при тестировании параллельного кода, имеющихся
методологиях и инструментарии.
Аннотация. В статье кратко рассматривается архитектура AMD64 компании AMD и ее
реализация EM64T компании Intel. Описаны особенности архитектуры, ее возможности,
достоинства и недостатки.