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

Интервал:

Закладка:

Сделать

Сигналом к отправке данных является событие FEvents[1]. Метод SendString, помещая данные в буфер, взводит это событие. Если все содержимое буфера за один раз отправить не удастся, то через некоторое время возникнет событие FD_WRITE, означающее готовность сокета к приему новых данных. Это событие привязано у нас к FEvents[2], поэтому при наступлении FEvents[2]тоже возможна отправка данных.

Для приема данных здесь также используется буфер. Прямой необходимости в этом нет — можно было, как и раньше, помещать данные непосредственно в переменную, хранящую длину строки, а затем и в саму строку. Сделано это в учебных целях, чтобы показать, как можно работать с подобным буфером. Буфер имеет фиксированный размер. Сначала мы читаем из сокета в этот буфер столько, сколько сможем, а потом начинаем разбирать полученное точно так же, как и раньше, копируя данные то в целочисленную, то в строковую переменную. Когда строковая переменная полностью заполняется, строка считается принятой, для пользователя выводится ответ на нее, а в буфер для отправки добавляется ответная строка. Достоинством такого способа является то, что, с одной стороны, за время обработки одного события сервер может прочитать несколько запросов от клиента (если буфер достаточно велик), но, с другой стороны, это не приводит к зацикливанию, если сообщения поступают непрерывно. Другими словами, разработчик здесь сам определяет, какой максимальный объем данных можно получить от сокета за один раз. Иногда это бывает полезно.

Теперь рассмотрим нить, обслуживающую слушающий сокет. Код этой нити приведен в листинге 2.64.

Листинг 2.64. Код нити, обслуживающей слушающий сокет

unit ListenThread;

{

Нить, следящая за подключением клиента к слушающему сокету.

При обнаружении подключения она создает новую нить для работы с подключившимся клиентом, а сама продолжает обслуживать "слушающий" сокет.

}

interface

uses

SysUtils, Classes, WinSock, WinSock2_Events;

type

TListenThread = class(TThread)

private

// Сообщение, которое нужно добавить в лог.

// Хранится в отдельном поле, т.к. метод, вызывающийся

// через Synchronize, не может иметь параметров.

FMessage: string;

// Сокет, находящийся в режиме прослушивания

FServerSocket: TSocket;

// События нити

// FEvents[0] используется для остановки нити

// FEvents[1] связывается с событием FD_ACCEPT

FEvents: array[0..1] of TWSAEvent;

// Список нитей клиентов

FClientThreads: TList;

// Если True, сервер посылает клиенту сообщения

// по собственной инициативе

FServerMsg: Boolean;

// Вспомогательный метод для вызова через Synchronize

procedure DoLogMessage;

protected

procedure Execute; override;

// Вывод сообщения в лог главной формы

procedure LogMessage(const Msg: string);

public

constructor Create(ServerSocket: TSocket; ServerMsg: Boolean);

destructor Destroy; override;

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

procedure StopServer;

end;

implementation

uses

MainServerUnit, ClientThread;

{ TListenThread }

// "Слушающий" сокет создается в главной нити,

// а сюда передается через параметр конструктора

constructor TListenThread.Create(ServerSocket: TSocket; ServerMsg: Boolean);

begin

FServerSocket := ServerSocket;

FServerMsg := ServerMsg;

// Создаем события

FEvents[0] := WSACreateEvent;

if FEvents[0] = WSA_INVALID_EVENT then

raise ESocketError.Create(

'Ошибка при создании события для сервера:' + GetErrorString);

FEvents[1] := WSACreateEvent;

if FEvents[1] = WSA_INVALID_EVENT then

raise ESocketError.Create(

'Ошибка при создании события для сервера: ' + GetErrorString);

if WSAEventSelect(FServerSocket, FEvents[1], FD_ACCEPT) = SOCKET_ERROR then

raise ESocketError.Create(

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

FClientThreads := TList.Create;

inherited Create(False);

end;

destructor TListenThread.Destroy;

begin

// Убираем за собой

FClientThreads.Free;

WSACloseEvent(FEvents[0]);

WSACloseEvent(FEvents[1]);

inherited;

end;

procedure TListenThread.Execute;

var

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

ClientSocket: TSocket;

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

ClientAddr: TSockAddr;

ClientAddrLen: Integer;

NetEvents: TWSANetworkEvents;

I: Integer;

WaitRes: Cardinal;

begin

LogMessage('Сервер начал работу');

// Начинаем бесконечный цикл

repeat

// Ожидание события с 15-секундным тайм-аутом

WaitRes :=

WSAWaitForMultipleEvents(2, @FEvents, False, 15000, False);

case WaitRes of

WSA_WAIT_EVENT_0:

// Событие FEvents[0] взведено - это означает, что

// сервер должен остановиться.

begin

LogMessage('Сервер получил сигнал завершения работы');

// Просто выходим из цикла, остальное сделает код после цикла

Break;

end;

WSA_WAIT_EVENT_0 + 1:

// Событие FEvents[1] взведено.

// Это должно означать наступление события FD_ACCEPT.

begin

// Проверяем, почему событие взведено,

// и заодно сбрасываем его

if WSAEnumNetworkEvents(FServerSocket, FEvents[1], NetEvents) = SOCKET_ERROR then

begin

LogMessage('Ошибка при получении списка событий: ' +

GetErrorString);

Break;

end;

// Защита от "тупой" ошибки - проверка того,

// что наступило нужное событие

if NetEvents.lNetworkEvents and FD_ACCEPT = 0 then

begin

LogMessage(

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

Break;

end;

// Проверка, не было ли ошибок

if NetEvents.iErrorCode[FD_ACCEPT_BIT] <> 0 then

begin

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

GetErrorString(NetEvents.iErrorCode[FD_ACCEPT_BIT]));

Break;

end;

ClientAddrLen := SizeOf(ClientAddr);

// Проверяем наличие подключения

ClientSocket :=

accept(FServerSocket, @ClientAddr, @ClientAddrLen);

if ClientSocket = INVALID_SOCKET then

begin

// Ошибка в функции accept возникает только тогда, когда

// происходит нечто экстраординарное. Продолжать работу

// в этом случае бессмысленно. Единственное возможное

// в нашем случае исключение - ошибка WSAEWOULDBLOCK,

// которая может возникнуть, если срабатывание события

// было ложным, и подключение от клиента отсутствует

if WSAGetLastError <> WSAEWOULDBLOCK then

begin

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

GetErrorString);

Break;

end;

end;

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

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

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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