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

Интервал:

Закладка:

Сделать

// BytesLeft - сколько байтов осталось получить от клиента

// или отправить ему на данном этапе

// Overlapped - структура для выполнения перекрытой операции

PConnection = ^TConnection;

TConnection = record

ClientSocket: TSocket;

ClientAddr: string;

MsgSize: Integer;

Msg: string;

Offset: Integer;

BytesLeft: Integer;

Overlapped: TWSAOverlapped;

end;

Основное отличие этого варианта типа TConnectionот того, что применялся ранее в примерах NonBlockingServerи AsyncSelectServer(см. разд. 2.1.16 и 2.2.6 , а также листинг 2.31) — это отсутствие поля Phase, которое хранит этап взаимодействия с клиентом. Разумеется, в программе OverlappedServerвзаимодействие с клиентом также разбивается на три этапа, но реализуется другой способ для того, чтобы различать этапы — для каждого этапа создается своя процедура завершения.

Примечание

Использование одной процедуры завершения для всех трех этапов и распознавание в ней этапов с помощью поля Phaseв случае перекрытого ввода-вывода также возможно. Рекомендуем написать такой вариант сервера в качестве самостоятельного упражнения.

Поле Overlappedсодержит структуру TWSAOverlapped, которой программа непосредственно не пользуется, она только передает указатель на эту структуру в функции WSARecvи WSASend. Напомним, что одновременно может выполняться несколько операций перекрытого ввода-вывода, но у каждой из этих операций должен быть свой экземпляр TWSAOverlapped. Гак как в нашем случае с одним клиентом в каждый момент времени может выполняться не более одной операции, мы создаем по одному экземпляру TWSAOverlappedна каждого клиента.

Функция для перекрытого подключения клиентов существует — это AcceptEx, с которой мы познакомимся в разд. 2.2.12 . Но она неудобна при работе совместно с WSARecvи WSASend, особенно в таком строго типизированном языке, как Delphi. Поэтому подключение клиентов мы будем отслеживать с помощью уже опробованной технологии асинхронных сокетов на сообщениях. Код запуска сервера OverlappedServer выглядит идентично коду запуска AsyncSelectServer (см. листинг 2.30): точно так же создается сокет, ставится в режим прослушивания, а затем его событие FD_ACCEPTпривязывается к сообщению WM_ACCEPTMESSAGE.

Сам обработчик WM_ACCEPTMESSAGEвыглядит теперь следующим образом (листинг 2.77).

Листинг 2.77. Обработчик сообщения WM_ ACCEPTMESSAGE

procedure TServerForm.WMAcceptMessage(var Msg: TWMSocketMessage);

var

NewConnection: PConnection;

// Сокет, который создается для вновь подключившегося клиента

ClientSocket: TSocket;

// Адрес подключившегося клиента

ClientAddr: TSockAddr;

// Длина адреса

AddrLen: Integer;

// Аргумент для перевода сокета в неблокирующий режим

Arg: u_long;

// Буфер для операции перекрытого чтения

Buf: TWSABuf;

NumBytes, Flags: DWORD;

begin

// Страхуемся от "тупой" ошибки

if Msg.Socket <> FServerSocket then

raise ESocketError.Create(

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

// Обрабатываем ошибку на сокете, если она есть

if Msg.SockError <> 0 then

begin

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

GetErrorString(Msg.SockError) +

#13#10'Сервер будет ocтановлен', mtError, [mbOK], 0);

ClearConnections;

closesocket(FServerSocket);

OnStopServer;

Exit;

end;

// Страхуемся от ещё одной "тупой" ошибки

if Msg.SockEvent <> FD_ACCEPT then

raise ESocketError.Create(

'Внутренняя ошибка сервера - неверное событие на сокете');

AddrLen := SizeOf(TSockAddr);

ClientSocket := accept(FServerSocket, @ClientAddr, @AddrLen);

if ClientSocket = INVALID_SOCKET then

begin

// Если произошедшая ошибка - WSAEWOULDBLOCK, это просто означает

// что на данный момент подключений нет, а вообще все а порядке,

// поэтому ошибку WSAEWOULDBLOCK мы просто игнорируем. Прочие же

// ошибки могут произойти только в случае серьезных проблем,

// которые требуют остановки сервера.

if WSAGetLastError <> WSAEWOULDBLOCK then

begin

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

GetErrorString + #13#10'Сервер будет остановлен',

mtError, [mbOK], 0);

ClearConnections;

closesocket(FServerSocket);

OnStopServer;

end;

end

else

begin

// Новый сокет наследует свойства слушающего сокета.

// В частности, он работает в асинхронном режиме,

// и его событие FD_ACCEPT связано с сообщением WM_ACCEPTMESSAGE.

// Так как нам это совершенно не нужно, отменяем асинхронный

// режим и делаем сокет блокирующим.

if WSAAsyncSelect(ClientSocket, Handle, 0, 0) = SOCKET_ERROR then

begin

MessageDlg('Ошибка при отмене асинхронного режима ' +

'подключившегося сокета:'#13#10 + GetErrorString,

mtError, [mbOK], 0);

closesocket(ClientSocket);

Exit;

end;

Arg := 0;

if ioctlsocket(ClientSocket, FIONBIO, Arg) = SOCKET_ERROR then

begin

MessageDlg('Ошибка при переводе подключившегося сокета ' +

'в блокирующий режим:'#13#10 + GetErrorString,

mtError, [mbOK], 0);

closesocket(ClientSocket);

Exit;

end;

// Создаем запись для нового подключения и заполняем ее

New(NewConnection);

NewConnection.ClientSocket := ClientSocket;

NewConnection.ClientAddr :=

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

Ord(ClientAddr.sin_addr.S_un_b.s_b1),

Ord(ClientAddr.sin_addr.S_un_b.s_b2),

Ord(ClientAddr.sin_addr.S_un_b.s_b3),

Ord(ClientAddr.sin_addr.S_un_b.s_b4),

ntohs(ClientAddr.sin_port)]);

NewConnection.Offset := 0;

NewConnection.BytesLeft := SizeOf(Integer);

NewConnection.Overlapped.hEvent := 0;

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

FConnections.Add(NewConnection);

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

NewConnection.ClientAddr);

// Начинаем перекрытый обмен с сокетом.

// Начинаем, естественно, с чтения длины строки,

// в качестве принимающего буфера используем NewConnection.MsgSize

Buf.Len := NewConnection.BytesLeft;

Buf.Buf := @NewConnection.MsgSize;

Flags := 0;

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

@NewConnection.Overlapped, ReadLenCompleted) = SOCKET_ERROR then

begin

if WSAGetLastError <> WSA_IO_PENDING then

begin

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

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

RemoveConnection(NewConnection);

end;

end;

end;

end;

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

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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