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

Тут можно читать онлайн А. Григорьев - О чём не пишут в книгах по Delphi - бесплатно ознакомительный отрывок. Жанр: comp-programming, издательство БХВ-Петербург, год 2008. Здесь Вы можете читать ознакомительный отрывок из книги онлайн без регистрации и SMS на сайте лучшей интернет библиотеки ЛибКинг или прочесть краткое содержание (суть), предисловие и аннотацию. Так же сможете купить и скачать торрент в электронном формате fb2, найти и слушать аудиокнигу на русском языке или узнать сколько частей в серии и всего страниц в публикации. Читателям доступно смотреть обложку, картинки, описание и отзывы (комментарии) о произведении.
  • Название:
    О чём не пишут в книгах по Delphi
  • Автор:
  • Жанр:
  • Издательство:
    БХВ-Петербург
  • Год:
    2008
  • Город:
    СПб
  • ISBN:
    978-5-9775-019003
  • Рейтинг:
    4.25/5. Голосов: 81
  • Избранное:
    Добавить в избранное
  • Отзывы:
  • Ваша оценка:
    • 80
    • 1
    • 2
    • 3
    • 4
    • 5

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

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

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

Для программистов

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

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

Интервал:

Закладка:

Сделать

if ClientSocket = INVALID_SOCKET then raise

ESocketException.Create(

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

// Создаем в динамической памяти новый экземпляр TConnection

// и заполняем его данными, соответствующими подключившемуся клиенту

New(NewConnection);

NewConnection.ClientSocket := ClientSocket;

NewConnection.ClientAddr :=

Format('%u.%u.%u.%u:%u',

Ord(ClientSockAddr.sin_addr.S_un_b.s_bl),

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));

NewConnection.Deleted := False;

// Добавляем соединение в список

Connections.Add(NewConnection);

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

NewConnection.ClientAddr));

end;

// Теперь проверяем готовность всех сокетов подключившихся клиентов.

// Так как множество SockSet не может содержать более чем FT_SETSIZE

// элементов, а размер списка Connections мы нигде не ограничиваем,

// приходится разбивать Connections на "куски" размером не более

// FD_SETSIZE и обрабатывать этот список по частям.

// Поэтому у нас появляется два цикла - внешний, который повторяется

// столько раз, сколько у нас будет кусков, и внутренний, который

// повторяется столько раз, сколько элементов в одном куске.

for J := 0 to Ceil(Connections.Count, FD_SETSIZE) - 1 do

begin

FD_ZERO(SockSet);

for I := FD_SETSIZE * J to Min(FD_SETSIZE * (J + 1) - 1, Connections.Count - 1) do

FD_SET(PConnection(Connections[I])^.ClientSocket, SockSet);

if select(0, @SockSet, nil, nil, @Timeout) = SOCKET_ERROR then

raise ESocketException.Create(

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

// Проверяем, какие сокеты функция select оставила в множестве,

// и вызываем для них ProcessSocketMessage. В этом есть некоторый

// риск, т.к. для того, чтобы select оставила сокет в множестве,

// достаточно, чтобы он получил хотя бы один байт от клиента,

// а не все сообщение. Поэтому может возникнуть такая ситуация,

// когда сервер получил только часть сообщения, но уже пытается

// прочитать сообщение целиком. Это приведет к блокированию нити,

// но вероятность блокирования на долгое время мы оцениваем как

// крайне низкую, т.к. оставшаяся часть сообщения, скорее всего,

// придет достаточно быстро, и поэтому идем на такой риск.

for I := FD_SETSIZE * J to Min(FD_SETSIZE * (J + 1) - 1, Connections.Count - 1) do

if FD_ISSET(PConnection(Connections[I])^.ClientSocket, SockSet) then

ProcessSocketMessage(PConnection(Connections[I])^);

end;

// Проверяем поле Deleted у всех соединений. Те, у которых

// оно равно True, закрываем: закрываем сокет, освобождаем память,

// удаляем указатель из списка. Цикл идет с конца списка к началу,

// потому что в ходе работы цикла верхняя граница списка

// может меняться, и цикл for снизу вверх мог бы привести

// к появлению индексов вне диапазона.

for I := Connections.Count - 1 downto 0 do

if PConnection(Connections[I])^.Deleted then

begin

closesocket(PConnection(Connections[I])^.ClientSocket);

Dispose(PConnection(Connections[I]));

Connections.Delete(I);

end;

Sleep(100);

until False;

Функции Ceilи Min, которые встречаются здесь, можно было бы заменить одноимёнными функциями из модуля Math. Но этот модуль входит не во все варианты поставки Delphi, и чтобы пример можно было откомпилировать в любом варианте поставки Delphi, мы описали их здесь самостоятельно (листинг 2.27).

Листинг 2.27. Функции Ceilи Min

// Функция Ceil возвращает наименьшее целое число X, удовлетворяющее

// неравенству X >= А / В

function Ceil(A, B: Integer): Integer;

begin

Result := A div B;

if A mod В <> 0 then Inc(Result);

end;

// Функция Min возвращает меньшее из двух чисел

function Min(А, В: Integer): Integer;

begin

if A < В then Result := A

else Result := B;

end;

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

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

Примечание

Многонитевой сервер в этом отношении надежнее: некорректное сообщение клиента заблокирует только ту нить, которая взаимодействует с этим клиентом, никак не влияя на остальные нити, работающие с другими клиентами.

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

2.1.15. Неблокирующий режим

Ранее мы столкнулись с функциями, которые могут надолго приостановить работу вызвавшей их нити, если действие не может быть выполнено немедленно. Это функции accept, recv, recvfrom, send, sendtoи connect(в дальнейшем в этом разделе мы не будем упоминать функции recvfromи sendto, потому что они в смысле блокирования эквивалентны функциям recvи sendсоответственно, и все, что будет здесь сказано о recvи send, применимо к recvfromи sendto). Такое поведение не всегда удобно вызывающей программе, поэтому в библиотеке сокетов предусмотрен особый режим работы сокетов — неблокирующий. Этот режим может быть установлен или отменен дм каждого сокета индивидуально с помощью функции ioctlsocket, имеющей следующий прототип:

function ioctlsocket(s: TSocket; cmd: DWORD; var arg: u_long): Integer;

Данная функция предназначена для выполнения нескольких логически мало связанных между собой действий. Возможно, у разработчиков первых версий библиотеки сокетов были причины экономить на количестве функций, потому что мы и дальше увидим, что иногда непохожие операции выполняются одной функцией. Но вернемся к ioctlsocket. Ее параметр cmdопределяет действие, которое выполняет функция, а также смысл параметра arg. Допустимы три значения параметра cmd: SIOCATMARK, FIONREADи FIONBIO. При задании SIOCATMARKпараметр argрассматривается как выходной: в нем возвращается ноль, если во входном буфере сокета имеются высокоприоритетные данные, и ненулевое значение, если таких данных нет (как уже было оговорено, мы в этой книге не будем касаться передачи высокоприоритетных данных).

Читать дальше
Тёмная тема
Сбросить

Интервал:

Закладка:

Сделать


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

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




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


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


Понравилась книга? Поделитесь впечатлениями - оставьте Ваш отзыв или расскажите друзьям

Напишите свой комментарий
x