Чтение онлайн

на главную - закладки

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

 if ClientSocket = INVALID_SOCKET then

raise ESocketException.Create(

'Ошибка при ожидании подключения клиента: ' + GetErrorString);

// При выводе сообщения не забываем,

 // что номер порта имеет сетевой формат

 WriteLn(OemString(' Зафиксировано подключение с адреса '),

Ord(ClientSockAddr.sin_addr.S_un_b.s_b1), '.',

Ord(ClientSockAddr.sin_addr.S_un_b.s_b2), '.',

Ord(ClientSockAddr.sin_addr.S_un_b.s_b3), '.',

Ord(ClientSockAddr.sin_addr.S_un_b.s_b4), ':',

ntohs(ClientSockAddr.sin_port));

 //
Цикл общения с клиентом. Продолжается до тех пор,

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

 // не возникнет ошибка

 repeat

// Читаем длину присланной клиентом строки и помещаем ее в StrLen

case ReadFromSocket(ClientSocket, StrLen, SizeOf(StrLen)) of

0: begin

WriteLn(OemString('Клиент закрыл соединение');

Break;

end;

– 1: begin

WriteLn(OemString('Ошибка при получении данных от клиента: ',

GetErrorString));

Break;

end;

end;

// Протокол не допускает строк нулевой длины

if StrLen <= 0 then

begin

WriteLn(OemString('Неверная длина строки от клиента: '), StrLen);

Break;

end;

// Установка длины строки в соответствии с полученным значением

SetLength(Str, StrLen);

// Чтение строки нужной длины

case ReadFromSocket(ClientSocket, Str[1], StrLen) of

0: begin

WriteLn(OemString('Клиент закрыл соединение'));

Break;

end;

– 1: begin

WriteLn(OemString( 'Ошибка при получении данных от клиента: ' +

GetErrorString));

Break;

end;

end;

WriteLn(OemString('Получена строка: ' + Str));

// Преобразование строки

Str :=

AnsiUpperCase(StringReplace(Str, #0, '#0', [rfReplaceAll])) +

' (Simplest server)';

// Отправка строки. Отправляется на один байт больше, чем

// длина строки, чтобы завершающий символ #0 тоже попал в пакет

if send(ClientSocket, Str[1], Length(Str) + 1, 0) < 0 then

begin

WriteLn(OemString('Ошибка при отправке данных клиенту: ' +

GetErrorString));

Break;

end;

WriteLn(OemString('Клиенту отправлен ответ: ' + Str));

// Завершение цикла обмена с клиентом

 until False;

 // Сокет для связи с клиентом
больше не нужен

 closesocket(ClientSocket);

until False;

Теперь перейдем к написанию клиента. Пример этого клиента находится на компакт-диске в папке SimpleClient, главное окно показано на рис. 2.4. Клиент должен вызывать только одну функцию, которая реально может блокировать вызвавшую ее нить, — функцию

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

Рис. 2.4. Главное окно программы SimpleClient

Таким образом, наш клиент будет очень простым: по кнопке Соединиться он будет соединяться с сервером, по кнопке Отправить — отправлять серверу сообщение и дожидаться ответа. Третья кнопка, Отсоединиться, служит для корректного завершения работы с сервером. Рассмотрим эти действия подробнее.

При соединении с сервером клиент должен создать сокет и вызвать функцию

connect
. Здесь мы не можем создать сокет один раз и потом пользоваться им на протяжении всего времени работы клиента, т.к. после закрытия соединения (неважно, корректного или из-за ошибки) сокет больше нельзя использовать. Поэтому при установлении соединения каждый раз приходится создавать новый сокет. Обработчик нажатия кнопки Соединиться приведен в листинге 2.16.

Листинг 2.16. Обработчик нажатия кнопки Соединиться

procedure TSimpleClientForm.BtnConnectClick(Sender: TObject);

var

 // Адрес сервера

 ServerAddr: TSockAddr;

begin

 // Формируем адрес сервера, к которому нужно подключиться

 FillChar(ServerAddr.sin_zero, SizeOf(ServerAddr.sin_zero), 0);

 ServerAddr.sin_family := AF_INET;

 ServerAddr.sin_addr.S_addr := inet_addr(PChar(EditIPAddress.Text));

 // Для совместимости со старыми версиями Delphi приводим

 // константу INADDR_ANY к типу u_long

 if ServerAddr.sin_addr.S_addr := u_long(INADDR_NONE)then

 begin

MessageDlg('Синтаксическая ошибка в IР-адресе', mtError, [mbOK], 0);

Exit;

 end;

 try

Поделиться:
Популярные книги

Жалкая

Макинтайер Эмили
3. Долго и Несчастливо
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Жалкая

Беглец

Бубела Олег Николаевич
1. Совсем не герой
Фантастика:
фэнтези
попаданцы
8.94
рейтинг книги
Беглец

Академия проклятий. Книги 1 - 7

Звездная Елена
Академия Проклятий
Фантастика:
фэнтези
8.98
рейтинг книги
Академия проклятий. Книги 1 - 7

Измена. Верни мне мою жизнь

Томченко Анна
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Верни мне мою жизнь

Измена

Рей Полина
Любовные романы:
современные любовные романы
5.38
рейтинг книги
Измена

Гардемарин Ее Величества. Инкарнация

Уленгов Юрий
1. Гардемарин ее величества
Фантастика:
городское фэнтези
попаданцы
альтернативная история
аниме
фантастика: прочее
5.00
рейтинг книги
Гардемарин Ее Величества. Инкарнация

Сердце для стража

Каменистый Артем
5. Девятый
Фантастика:
фэнтези
боевая фантастика
9.20
рейтинг книги
Сердце для стража

Черный Маг Императора 11

Герда Александр
11. Черный маг императора
Фантастика:
юмористическое фэнтези
попаданцы
аниме
фэнтези
5.00
рейтинг книги
Черный Маг Императора 11

Имя нам Легион. Том 3

Дорничев Дмитрий
3. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 3

Жена фаворита королевы. Посмешище двора

Семина Дия
Фантастика:
фэнтези
5.00
рейтинг книги
Жена фаворита королевы. Посмешище двора

Как я строил магическую империю 5

Зубов Константин
5. Как я строил магическую империю
Фантастика:
попаданцы
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 5

Блуждающие огни 2

Панченко Андрей Алексеевич
2. Блуждающие огни
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
альтернативная история
фэнтези
5.00
рейтинг книги
Блуждающие огни 2

Ратник

Ланцов Михаил Алексеевич
3. Помещик
Фантастика:
альтернативная история
7.11
рейтинг книги
Ратник

Маленькая слабость Дракона Андреевича

Рам Янка
1. Танцы на углях
Любовные романы:
современные любовные романы
эро литература
5.25
рейтинг книги
Маленькая слабость Дракона Андреевича