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

Интервал:

Закладка:

Сделать

Как мы уже говорили ранее, в программе OverlappedServerесть три разных функции завершения: ReadLenCompleted, ReadMsgCompletedи SendMsgCompleted. Последовательность работы с ними такая: сначала для чтения длины строки вызывается WSARecv, в качестве буфера передастся Connection.MsgSize, в качестве функции завершения — ReadLenCompleted(это мы уже видели в листинге 2.77). Когда вызывается ReadLenCompleted, это значит, что операция чтения уже завершена и прочитанная длина находится в Connection.MsgSize. Поэтому в функции ReadLenCompletedвыделяем нужный размер для строки Connection.Msgи запускаем следующую операцию перекрытого чтения — с буфером Connection.Msgи функцией завершения ReadMsgCompleted. В этой функции полученная строка показывается пользователю, формируется ответ, и запускается следующая операция перекрытого ввода-вывода — отправка строки клиенту. В качестве буфера в функцию WSASendпередаётся Connection.Msg, а в качестве функции завершения — SendMsgCompleted. В функции SendMsgCompletedвновь вызывается WSARecvс буфером Connection.MsgSizeи функцией завершения ReadLenCompleted, и таким образом сервер возвращается к первому этапу взаимодействия с клиентом.

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

Листинг 2.78. Функции завершения

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

// для перекрытого чтения длины строки

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

var

// Указатель на соединение

Connection: PConnection;

// Указатель на буфер

Buf: TWSABuf;

// Параметры для WSARecv

NumBytes, Flags: DWORD;

begin

// Для идентификации операции в функцию передается указатель

// на запись TWSAOverlapped. Ищем по этому указателю

// подходящее соединение в списке FConnections.

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

// Страховка от "тупой" ошибки

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

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

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

ServerForm.RemoveConnection(Connection);

end

else if Connection.BytesLeft = 0 then

begin

// Длина строки прочитана целиком

if Connection.MsgSize <= 0 then

begin

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

' — получена неверная длина строки ' +

IntToStr(Conneсtion.MsgSizе));

ServerForm.RemoveConnection(Connection);

Exit;

end;

// Делаем строку нужной длины

SetLength(Connection.Msg, Connection.MsgSize);

// Данные пока не прочитаны, поэтому смещение - ноль,

// осталось прочитать полную длину.

Connection.Offset := 0;

Connection.BytesLeft := Connection.MsgSize;

// Заносим размер буфера и указатель на него в Buf.

// Данные будут складываться в строку,

// на которую ссылается Connection.Msg.

Buf.Len := Connection.MsgSize;

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

// Вызываем WSARecv для чтения самой строки

Flags := 0;

if WSARecv(Connect ion.ClientSocket, @Buf, 1, NumBytes, Flags,

@Connection.Overlapped, ReadMsgCompleted) = SOCKET_ERROR then

begin

if WSAGetLastError <> WSA_IO_PENDING then

begin

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

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

ServerForm.RemoveConnection(Connection);

end;

end;

end

else

begin

// Connection.BytesLeft < 0 - длина строки

// прочитана не до конца.

// Увеличиваем смещение на число прочитанных байтов

Inc(Connection.Offset, cdTransferred);

// Формируем буфер для чтения оставшейся части длины

Buf.Len := Connection.BytesLeft;

Buf.Buf := PChar(@Connection.MsgSize) + Connection.Offset;

// вызываем WSARecv для чтения оставшейся части длины строки

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

ServerForm.RemoveConnection(Connection);

end;

end;

end;

end;

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

// для перекрытого чтения строки.

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

procedure ReadMsgCompleted(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 :=

AnsiUpperCase(StringReplace(Connection.Msg, #0,

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

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

Connection.Offset := 0;

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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