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

Интервал:

Закладка:

Сделать

// нитью в петле сообщений, вызов метода WaitFor мог бы привести

// к взаимной блокировке: главная нить ждала бы, когда завершится

// нить TListenThread, а та, в свою очередь - когда главная нить

// выполнит Synchronize. Чтобы этого не происходило, организуется

// ожидание с локальной петлей сообщений.

if Assigned(FListenThread) then

begin

FListenThread.StopServer;

while Assigned(FListenThread) do

begin

Application.ProcessMessages;

Sleep(10);

end;

end;

end;

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

Чтобы увидеть все возможности сервера, потребуется новый клиент. На компакт-диске он называется EventSelectClient, но "EventSelect" в данном случае означает только то, что клиент является парным к серверу EventSelectServer. Сам клиент функцию WSAEventSelectне использует, поскольку она неудобна, когда нужно работать только с одним сокетом. Поэтому клиент работает в асинхронном режиме, основанном на сообщениях, т.е. посредством функции WSAAsyncSelect.

Клиент может получать от сервера сообщения двух видов: те. которые сервер посылает в ответ на запросы клиента, и те, которые он посылает по собственной инициативе. Но различить эти сообщения клиент не может: например, если клиент отправляет запрос серверу, а потом получает от него сообщение, он не может определить, то ли это сервер ответил на его запрос, то ли именно в этот момент сервер сам отправил клиенту свое сообщение. Соответственно, сообщения обоих типов читает один и тот же код.

Примечание

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

Подключение клиента к серверу выполняется точно так же, как в листинге 2.16, за исключением того, что после выполнения функции connectсокет переводится в асинхронный режим, и его события FD_READи FD_CLOSEсвязываются с сообщением WM_SOCKETMESSAGE. Обработчик этого сообщения приведен в листинге 2.66.

Листинг 2.66. Получение данных клиентом

procedure TESClientForm.WMSocketMessage(var Msg: TWMSocketMessage);

const

// Размер буфера для получения данных

RecvBufSize = 4096;

var

// Буфер для получения данных

RecvBuf: array[0..RecvBufSize - 1] of Byte;

RecvRes: Integer;

P: Integer;

begin

// Защита от "тупой" ошибки

if Msg.Socket <> FSocket then

begin

MessageDlg('Внутренняя ошибка программы — неверный сокет',

mtError, [mbOK], 0);

Exit;

end;

if Msg.SockError <> 0 then

begin

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

GetErrorString(Msg.SockError), mtError, [mbOK], 0);

OnDisconnect;

Exit;

end;

case Msg.SockEvent of

FD_READ:

// Получено сообщение от сервера

begin

// Читаем столько, сколько можем

RecvRes := recv(FSocket, RecvBuf, RecvBufSize, 0);

if RecvRes > 0 then

begin

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

P := Length(FRecvStr);

SetLength(FRecvStr, P + RecvRes);

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

Move(RecvBuf, FRecvStr[Р + 1], RecvRes);

// В строке может оказаться несколько строк от сервера,

// причем последняя может прийти не целиком.

// Ищем в строке символы #0, которые, согласно протоколу,

// являются разделителями строк.

P := Pos(#0, FRecvStr));

while P > 0 do

begin

AddMessageToRecvMemo('Сообщение от сервера: ' +

Copy(FRecvStr, 1, P - 1));

// Удаляем из строкового буфера выведенную строку

Delete(FRecvStr, 1, P);

P := Pos(#0, FRecvStr);

end;

end

else if RecvRes = 0 then

begin

MessageDlg('Сервер закрыл соединение'#13#10 +

GetErrorString, mtError, [mbOK], 0);

OnDisconnect;

end

else

begin

if WSAGetLastError <> WSAEWOULDBLOCK then

begin

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

GetErrorString, mtError, [mbOK], 0);

OnDisconnect;

end;

end;

end;

FD_CLOSE: begin

MessageDlg('Сервер закрыл соединение', mtError, [mbOK], 0);

shutdown(FSocket, SD_BOTH);

OnDisconnect;

end;

else begin

MessageDlg('Внутренняя ошибка программы — неизвестное событие ' +

IntToStr(Msg.SockEvent), mtError, [mbOK], 0);

OnDisconnect;

end;

end;

end;

Здесь мы используем новый способ чтения данных. Он во многом похож на тот, который применен в сервере. Функция recvвызывается один раз за один вызов обработчика значений и передаст данные в буфер фиксированного размера RecvBuf. Затем в буфере ищутся границы отдельных строк (символы #0), строки, полученные целиком, выводятся. Если строка получена частично (а такое может случиться не только из-за того, что она передана по частям, но и из-за того, что в буфере просто не хватило место для приема ее целиком), её начало следует сохранить в отдельном буфере, чтобы добавить к тому, что будет прочитано при следующем событии FD_READ. Этот буфер реализуется полем FRecvStrтипа string. После чтения к содержимому этой строки добавляется содержимое буфера RecvBuf, а затем из строки выделяются все подстроки, заканчивающиеся на #0. То, что остается в строке FRecvStrпосле этого, — это начало строки, прочитанной частично. Оно будет учтено при обработке следующего события FD_READ.

Примечание

Описанный алгоритм разбора буфера прост, но неэффективен с точки зрения нагрузки на процессор и использования динамической памяти, особенно в тех случаях, когда в буфере RecvBufоказывается сразу несколько строк. Это связано с тем, что при добавлении содержимого RecvBufк FRecvStrи последующем поочередном удалении строк из FRecvStrпроисходит многократное перераспределение памяти, выделенной для строки. Алгоритм можно оптимизировать: все строки, которые поместились в RecvBufцеликом, выделять непосредственно из этого буфера, не помещая в FRecvStr, а помещать туда только то, что действительно нужно сохранить между обработкой разных событий FD_READ. Реализацию такого алгоритма рекомендуем выполнить в качестве самостоятельного упражнения.

При отправке данных вероятность того, что функция send не сможет быть выполнена сразу, достаточно мала. Кроме того, как мы уже говорили, блокировка клиента при отправке данных часто бывает вполне приемлема из-за редкости и непродолжительности. Таким образом, блокирующий режим из-за своей простоты наиболее удобен при отправке данных серверу клиентом. Но мы не можем перевести сокет, работающий в асинхронном режиме, в блокирующий режим на время отправки, зато можем этот режим имитировать. Занимается этим метод SendString(листинг 2.67).

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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