Чтобы протестировать пример, посмотрим, как можно принимать и передавать данные. Мы уже знаем, что это будет происходить в отдельном потоке с именем CPCIientThread. Давайте создадим этот поток и рассмотрим его содержимое Для этого выполните команду меню File ► New ► Other, и перед вами появится диалоговое окно выбора типа создаваемого файла (рис. 4.1).

4.10.2. Получение и передача сетевых данных

Рис. 4.1. Выбор типа создаваемого файла

Перейдите на вкладку New и выберите значок Thread Object. Нажмите кнопку ОК Появится диалоговое окно ввода имени класса (рис. 4.2).

4.10.2. Получение и передача сетевых данных

Рис. 4.2. Ввод имени класса

В поле Class Name нужно ввести имя TCPCIientThread. Нажмите кнопку OK Delphi создаст шаблон для будущего потока и откроет на экране соответствующий модуль.

В листинге 4.4 приведен полный код модуля потока. Допишите недостающие части в вашем модуле, и программу можно будет считать завершенной.

Листинг 4.4. Поток для получения и отправки данных

unit ТСРС11entUnit:

interface uses
Classes. WinSock. Windows;
type TCPClientThread = class(TThread) private {Private declarations} protected
procedure Execute: override, public
Sock. TSOCKET;
end:
implementation {TCPClientThread}
procedure TCPC1ientThread.Execute: var
sRecvBuff. sSendBuff: array [0 .255] of char;
ret- Integer: s. String;
begin
while(true) do begin
ret .= recv(sock. sRecvBuff. 1024. 0):
if (ret = 0) then
Continue

else if (ret = S0CKET_ERR0R) then begin MessageBox(0, 'Ошибка получения данных' 'Внимание!1!'. 0): break:

end:
s := sRecvBuff, if s[Length(s)] = #10 then
s .= Copy(s. 1. Length(s)-2);
if s<>'get' then
exit;
sSendBuff •= 'Command get OK'.

ret := send(sock. sSendBuff. sizeof(sSendBuff). 0). if (ret = S0CKET_ERR0R) then begin MessageBox(0. Ошибка передачи данных' 'Внимание!!!' 0); break:

end;
end:
CloseSocket(sock), end;
end.

Рассмотрим, что происходит в модуле потока. Когда Delphi создал шаблон, то в разделе uses был только один модуль CI asses. Так как будут использоваться сетевые функции, нам нужно подключить модуль WmSock. Помимо эгого понадобятся функции Windows API для отображения окна сообщения об ошибке (функция MessageBox), поэтому подключаем модуль Windows.

В объявлении объекта потока добавляем раздел public с одной переменной Sock типа TS0CKET.

Все остальные изменения касаются метода Execute, который автоматически запускается при старте потока. Для чтения данных вызывается функция recv. Она блокирует выполнение программы в ожидании данных от клиента Это не очень хорошо, потому что клиент может вообще никогда не прислать нам данные (например, прервалось соединение или на клиенте произошла ошибка) и программа просто зависнет. Именно поэтому я всегда при программировании в блокирующем режиме убираю обработку клиента в отдельный поток.

В нашей программе основная форма блокируется, потому что после запуска сервера стартует бесконечный цикл обработки принятых клиентов. Это тоже не очень удобно, потому что окно не будет откликаться. Можно было бы вынести эту операцию в отдельный поток, но я не стал усложнять задачу, потому что немного позже мы познакомимся с неблокирующими сокетами.

Если с клиента пришла текстовая команда "get", то отвечаем клиенту сообщением "Command get ОК" с помощью функции send. По завершении работы цикла закрываем сокет функцией CloseSocket.

ПРИМЕЧАНИЕ

Исходный код рассмотренного здесь примера находится на компакт-диске в каталоге Sources\ch04\TCPServer.

4.10.1. Создание сервера || Оглавление || 4.10.3. Тестирование сервера


Delphi в шутку и всерьез: что умеют хакеры



Новости за месяц

  • Январь
    2022
  • Пн
  • Вт
  • Ср
  • Чт
  • Пт
  • Сб
  • Вс