MyBooks.club
Все категории

А. Григорьев - О чём не пишут в книгах по Delphi

На сайте mybooks.club вы можете бесплатно читать книги онлайн без регистрации, включая А. Григорьев - О чём не пишут в книгах по Delphi. Жанр: Программирование издательство -,. Доступна полная версия книги с кратким содержанием для предварительного ознакомления, аннотацией (предисловием), рецензиями от других читателей и их экспертным мнением.
Кроме того, на сайте mybooks.club вы найдете множество новинок, которые стоит прочитать.

Название:
О чём не пишут в книгах по Delphi
Издательство:
-
ISBN:
-
Год:
-
Дата добавления:
17 сентябрь 2019
Количество просмотров:
244
Читать онлайн
А. Григорьев - О чём не пишут в книгах по Delphi

А. Григорьев - О чём не пишут в книгах по Delphi краткое содержание

А. Григорьев - О чём не пишут в книгах по Delphi - описание и краткое содержание, автор А. Григорьев, читайте бесплатно онлайн на сайте электронной библиотеки mybooks.club
Рассмотрены малоосвещённые вопросы программирования в Delphi. Описаны методы интеграции VCL и API. Показаны внутренние механизмы VCL и приведены примеры вмешательства в эти механизмы. Рассмотрено использование сокетов в Delphi: различные механизмы их работы, особенности для протоколов TCP и UDP и др. Большое внимание уделено разбору ситуаций возникновения ошибок и получения неверных результатов в "простом и правильном" коде. Отдельно рассмотрены особенности работы с целыми, вещественными и строковыми типами данных, а также приведены примеры неверных результатов, связанных с ошибками компилятора, VCL и др. Для каждой из таких ситуаций предложены методы решения проблемы. Подробно рассмотрен синтаксический анализ в Delphi на примере арифметических выражений. Многочисленные примеры составлены с учётом различных версий: от Delphi 3 до Delphi 2007. Прилагаемый компакт-диск содержит примеры из книги.Для программистов

О чём не пишут в книгах по Delphi читать онлайн бесплатно

О чём не пишут в книгах по Delphi - читать книгу онлайн бесплатно, автор А. Григорьев

    'Ошибка при инициализации библиотеки WinSock');

  // Создание сокета, который затем будет "слушать" порт

  MainSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if MainSocket = INVALID_SOCKET then

   raise ESocketException.Create(

    'Невозможно создать слушающий сокет: ' + GetErrorString');

  // Формирование адреса для "слушающего" сокета

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

  MainSockAddr.sin_family := AF_INET;

  // Выбор IP-адреса доверяем системе

  MainSockAddr.sin_addr.S_addr := INADDR_ANY;

  // Порт назначаем, не забывая перевести его номер в сетевой формат

  MainSockAddr.sin_port := htons(Port);

  // Привязка сокета к адресу

  if bind(MainSocket, MainSockAddr, SizeOf(MainSockAddr)) = SOCKET_ERROR then

   raise ESocketException.Create(

    'Невозможно привязать слушающий сокет к адресу: ' +

    GetErrorString);

  // Установка сокета в режим прослушивания

  if listen(MainSocket, SOMAXCONN) = SOCKET_ERROR then

   raise ESocketException.Create(

    'Невозможно установить сокет в режим прослушивания: ' +

    GetErrorString);

  WriteLn(OemString('Сервер успешно начал прослушивание порта '), Port);

  ...

  // Основная часть сервера приведена в листинге 2.15

  ...

 except

  on Е: ESocketException do

   WriteLn(OemString(E.Message));

  on E: Exception do

   WriteLn(OemString('Неожиданное исключение ' + E.ClassName +

    ' с сообщением ' + E.Message));

 end;

end.

Основная часть кода сервера — это два цикла, один из которых вложен в другой (листинг 2.15). Перед внешним циклом сервер создает сокет и переводит его в режим прослушивания, и внешний цикл начинается с вызова функции accept. Завершение accept указывает на подключение клиента. После этого начинается внутренний цикл, который состоит из получения сообщений от клиента, преобразования строки и отправки ответа. Внутренний цикл завершается, когда соединение разрывается либо самим клиентом, либо из-за ошибки в сети. После этого управление вновь передается на начало внешнего цикла, т.е. на accept, и сервер может принять подключение другого клиента (или повторное подключение того же клиента).

Листинг 2.15. Основная часть сервера SimplestServer

// Начало цикла подключения и общения с клиентом

repeat

 ClientSockAddrLen := SizeOf(ClientSockAddr);

 // Принимаем подключившегося клиента. Для общения с ним создается новый

 // сокет, дескриптор которого помещается в ClientSocket.

 ClientSocket :=

  accept(MainSocket, @ClientSockAddr, @ClientSockAddrLen);

 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

  ServerAddr.sin_port := htons(StrToInt(EditPort.Text));

  // Создание сокета

  FSocket := socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

  if FSocket = INVALID_SOCKET then

  begin

   MessageDlg('Ошибка при создании сокета: '#13#10 +

    GetErrorString, mtError, [mbOK], 0);

   Exit;

  end;

  // Подключение к серверу

  if connect(FSocket, ServerAddr, SizeOf(ServerAddr)) < 0 then

  begin

   MessageDlg('Ошибка при установлении подключения: '#13#10 +


А. Григорьев читать все книги автора по порядку

А. Григорьев - все книги автора в одном месте читать по порядку полные версии на сайте онлайн библиотеки mybooks.club.


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

Отзывы читателей о книге О чём не пишут в книгах по Delphi, автор: А. Григорьев. Читайте комментарии и мнения людей о произведении.

Прокомментировать
Подтвердите что вы не робот:*
Подтвердите что вы не робот:*
Все материалы на сайте размещаются его пользователями.
Администратор сайта не несёт ответственности за действия пользователей сайта..
Вы можете направить вашу жалобу на почту librarybook.ru@gmail.com или заполнить форму обратной связи.