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

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

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

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

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

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

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

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

 if Connection = nil then

 begin

  ServerForm.AddMessageToLog(

   'Внутренняя ошибка программы - не найдено соединение');

  Exit;

 end;

 if dwError <> 0 then

 begin

  ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +

   ' ошибка при чтении строки: ' + GetErrorString(dwError));

  ServerForm.RemoveConnection(Connection);

  Exit;

 end;

 Dec(Connection.BytesLeft, cdTransferred);

 if Connection.BytesLeft < 0 then

 begin

  ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +

   ' - внутренняя ошибка программы: получено больше байтов, ' +

   'чем ожидалось');

  ServerForm.RemoveConnection(Connection);

 end

 else if Connection.BytesLeft = 0 then

 begin

  // Строка получена целиком. Выводим ее на экран.

  ServerForm.AddMessageToLog('От клиента ' + Connection.ClientAddr +

   ' получена строка: ' + Connection.Msg);

  // Формируем ответ

  Connection.Msg :=

   AnsiUpperCase(StringReplace(Connection.Msg, #0,

   '#0', [rfReplaceAll])) + ' (Overlapped server)'#0;

  // Смещение - ноль, осталось отправить полную длину

  Connection.Offset := 0;

  Connection.BytesLeft := Length(Connection.Msg);

  // Формируем буфер из строки Connection.Msg

  Buf.Len := Connection.BytesLeft;

  Buf.Buf := Point(Connection.Msg);

  // Отправляем строку

  if WSASend(Connection.ClientSocket, @Buf, 1, NumBytes, 0,

   @Connection.Overlapped, SendMsgCompleted) = SOCKET_ERROR then

  begin

   it WSAGetLastError <> WSA_IO_PENDING then

   begin

    ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +

     ' - ошибка при отправке строки: ' + GetErrorString);

    ServerForm.RemoveConnection(Connection);

   end;

  end;

 end

 else

 begin

  // Connection.BytesLeft < 0 - строка прочитана частично

  Inc(Connection.Offset, cdTransferred);

  // Формируем буфер из непрочитанного остатка строки

  Buf.Len := Connection.BytesLeft;

  Buf.Buf := PChar(Connection.Msg) + Connection.Offset;

  // Читаем остаток строки

  Flags := 0;

  if WSARecv(Connection.ClientSocket, @Buf, 1, NumBytes, Flags,

   @Connection.Overlapped, ReadMsgCompleted) = SOCKET_ERROR then

  begin

   if WSAGetLastError <> WSA_IO_PENDING then

   begin

    ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +

     ' - ошибка при чтении строки: ' + GetErrorString);

    ServerForm.RemoveConnection(Connection);

   end;

  end;

 end;

end;


// Функция SendMsgCompleted используется в качестве функции завершения

// для перекрытой отправки строки.

// Во многом она аналогична функции ReadLenCompleted

procedure SendMsgCompleted(dwError: DWORD; cdTransferred: DWORD; lpOverlapped: PWSAOverlapped; dwFlags: DWORD); stdcall;

var

 Connection: PConnection;

 Buf: TWSABuf;

 NumBytes, Flags: DWORD;

begin

 Connection := ServerForm.GetConnectionByOverlapped(lpOverlapped);

 if Connection = nil then

 begin

  ServerForm.AddMessageToLog(

   'Внутренняя ошибка программы - не найдено соединение');

  Exit;

 end;

 if dwError <> 0 then

 begin

  ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +

   ' - ошибка при отправке строки: ' + GetErrorString(dwError));

  ServerForm.RemoveConnection(Connection);

  Exit;

 end;

 Dec(Connection.BytesLeft, cdTransferred);

 if Connection.BytesLeft < 0 then

 begin

  ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +

   ' — внутренняя ошибка программы: отправлено больше байтов, ' +

   'чем ожидалось');

  ServerForm.RemoveConnection(Connection);

 end

 else if Connection.BytesLeft = 0 then

 begin

  // Строка отправлена целиком. Выводим сообщение об этом.

  ServerForm.AddMessageToLog('Клиенту ' + Connection.ClientAddr +

   ' отправлена строка: ' + Connection.Msg);

  // Очищаем строку, чтобы зря не занимала память

  Connection.Msg := '';

  // Теперь будем снова читать длину строки

  Connection.Offset := 0;

  Connection.BytesLeft := SizeOf(Integer);

  // Читать будем в Connection.MsgSize

  Buf.Len := Connection.BytesLeft;

  Buf.Buf := @Connection.MsgSize;

  Flags := 0;

  if WSARecv(Connection.ClientSocket, @Buf, 1, NumBytes, Flags,

   @Connection.Overlapped, ReadLenCompleted) = SOCKET_ERROR then

  begin

   if WSAGetLastError <> WSA_IO_PENDING then

   begin

    ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +

     ' - ошибка при чтении длины строки: ' + GetErrorString);

    ServerForm.RemoveConnection(Connection);

   end;

  end;

 end

 else

 begin

  // Строка отправлена не полностью

  Inc(Connection.Offset, cdTransferred);

  // Формируем буфер из остатка строки

  Buf.Len := Connection.BytesLeft;

  Buf.Buf := PChar(Connection.Msg) + Connection.Offset;

  if WSASend(Connection.ClientSocket, @Buf, 1, NumBytes, 0,

   @Connection.Overlapped, SendMsgCompleted) = SOCKET_ERROR then

  begin

   if WSAGetLastError <> WSA_IO_PENDING then

   begin

    ServerForm.AddMessageToLog('Клиент ' + Connection.СlientAddr +

     ' - ошибка при отправке строки: ' + GetErrorString);

    ServerForm.RemoveConnection(Connection);

   end;

  end;

 end;

end;

Чтобы это все заработало, остался последний штрих: нить нужно время от времени переводить в состояние ожидания. Мы будем это делать, вызывая SleepEx с нулевым тайм-аутом по сигналам от таймера. В получившемся сервере трудно увидеть все преимущества перекрытого ввода-вывода. Это и неудивительно, потому что его главное достоинство — высокая производительность при большом количестве подключений. Перекрытый ввод-вывод ориентирован на создание серверов, интенсивно взаимодействующих с многими клиентами, а на таком маленьком сервере, как OverlappedServer, он выглядит несколько тяжеловесно, хотя и позволяет получить вполне работоспособный вариант.

2.2.11. Многоадресная рассылка

При описании стека протоколов TCP/IP мы упоминали протокол IGMP - дополнение к протоколу IP, позволяющее назначать нескольким узлам групповые адреса. С помощью этого протокола можно группе сокетов назначить один IP-адрес, и тогда все пакеты, отправленные на этот адрес, будут получать все сокеты, входящие в группу. Заметим, что не следует путать группы сокетов в терминах IGMP, и группы сокетов в терминах WinSock (поддержка групп сокетов в WinSock пока отсутствует, существуют только зарезервированные для этого параметры в некоторых функциях).

Мы уже говорили, что сетевая карта получает все IP-пакеты, которые проходят через ее подсеть, но выбирает из них только те, которые соответствуют назначенному ей MAC- и IP-адресу. Существуют два режима работы сетевых карт. В первом выборка пакетов осуществляется аппаратными средствами карты, во втором — программными средствами драйвера. Аппаратная выборка осуществляется быстрее и не загружает центральный процессор, но ее возможности ограничены. В частности, у некоторых старых карт отсутствует аппаратная поддержка IGMP, поэтому они не могут получать пакеты, отправленные на групповой адрес, без переключения в режим программной выборки. Более современные сетевые карты способны запоминать несколько (обычно 16 или 32) групповых адресов, и, пока количество групповых адресов не превышает этот предел, могут осуществлять аппаратную выборку пакетов с учетом групповых адресов.

Windows 95 и NT 4 используют сетевые карты в режиме программной выборки пакетов. Windows 98 и 2000 и выше по умолчанию устанавливают сетевые карты в режим аппаратной выборки пакетов. При этом Windows 2000 может переключать карту в режим программной выборки, если число групповых адресов, с которых компьютер должен принимать пакеты, превышает ее аппаратные возможности. Windows 98 такой возможностью не обладает, поэтому программа, выполняемая в этой среде, может столкнуться с ситуацией, когда сокет не сможет присоединиться к групповому адресу из-за нехватки аппаратных ресурсов сетевой карты (программа при этом получит ошибку WSAENOBUFS).

WinSock предоставляет достаточно широкие возможности по управлению многоадресной рассылкой, но для их использования необходимо, чтобы выбранный сетевой протокол поддерживал все эти возможности. Поддержка многоадресной рассылки протоколом IP достаточно скудна по сравнению, например, с протоколами, применяющимися в сетях ATM. Здесь мы будем рассматривать только те возможности WinSock по поддержке многоадресной рассылки, которые совместимы с протоколом IP.

Протокол TCP не поддерживает многоадресную рассылку, поэтому все, что далее будет сказано, относится только к протоколу UDP. Отметим также, что при многоадресной рассылке через границы подсетей маршрутизаторы должны поддерживать передачу многоадресных пакетов. Глава "Многоадресная рассылка" в [3], к сожалению, содержит множество неточностей. Далее мы будем обращать внимание на эти неточности, чтобы облегчить чтение этой книги.


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

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


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

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

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