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

Интервал:

Закладка:

Сделать

Исходный сокет, определяемый параметром s, остается в режиме прослушивания. Если сервер поддерживает одновременное соединение с несколькими клиентами, то функция acceptможет быть вызвана многократно. Каждый раз при этом будет создаваться новый сокет, обслуживающий одно конкретное соединение: протокол TCP и библиотека сокетов гарантируют, что данные, посланные клиентами, попадут в буферы соответствующих сокетов и не будут перемешаны.

Для получения целостной картины кратко повторим все сказанное. Для установления соединения сервер должен, во-первых, создать сокет с помощью функции socket, а во-вторых, привязать его к адресу с помощью функции bind. Далее сокет должен быть переведен в режим ожидания с помощью listen, а потом с помощью функции acceptсоздается новый сокет, обслуживающий соединение, установленное клиентом. После этого сервер может обмениваться данными с клиентом. Клиент же должен создать сокет, при необходимости привязки к конкретному порту вызвать bind, и затем вызвать connectдля установления соединения. После успешного завершения этой функции клиент может обмениваться данными с сервером. Это иллюстрируют листинги 2.11 и 2.12.

Листинг 2.11. Код сервера

var

S, AcceptedSock: TSocket;

Addr: TSockAddr;

Data: TWSAData;

Len: Integer;

begin

WSAStartup($101, Data);

S := socket(AF_INET, SOCK_SТREAМ, 0);

Addr.sin_family := FF_INET;

Addr.sin_port := htons(3030);

Addr.sin_addr.S_addr := INADDR_ANY;

FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);

bind(S, Addr, SizeOf(TSockAddr));

listen(S, SOMAXCONN);

Len := SizeOf(TSockAddr);

AcceptedSock := accept(S, @Addr, @Len);

{

Теперь Addr содержит адрес клиента, с которым установлено соединение, а AcceptedSock - дескриптор, обслуживающий это соединение. Допустимы следующие действия:

send(AcceptedSock, ...) - отправить данные клиенту

recv(AcceptedSock, ...) - получить данные от клиента

accept(...) - установить соединение с новым клиентом

}

Здесь сокет сервера привязывается к порту с номером 3030. В общем случае разработчик сервера сам должен выбрать порт из диапазона 1024–65 535.

Листинг 2.12. Код клиента

var

S: TSocket;

Addr: TSockAddr;

Data: TWSAData;

begin

WSAStartup($101, Data);

S := socket(AF_INET, SOCK_STREAM, 0);

Addr.sin_family := AF_INET;

Addr.sin_port := htons(3030);

Addr.sin_addr.S_addr := inet_addr(...);

FillChar(Addr.sin_zero, SizeOf(Addr.sin_zero), 0);

connect(S, Addr, SizeOf(TSockAddr));

{

Теперь соединение установлено. Допустимы следующие действия:

send(S, ...) - отправить данные серверу

recv(S, ...) — получить данные от сервера

}

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

Если на момент вызова функции acceptочередь соединений пуста, то нить, вызвавшая ее, блокируется до тех пор, пока какой-либо клиент не подключится к серверу. С одной стороны, это удобно: сервер может не вызывать функцию acceptв цикле до тех пор, пока она не завершится успехом, а вызвать ее один раз и ждать, когда подключится клиент. С другой стороны, это создает проблемы тем серверам, которые должны взаимодействовать с несколькими клиентами. Действительно, пусть функция acceptуспешно завершилась и в распоряжении программы оказались два сокета: находящийся в режиме ожидания новых подключений и созданный для обслуживания уже существующего подключения. Если вызвать accept, то программа не сможет продолжить работу до тех пор, пока не подключится еще один клиент, а это может произойти через очень длительный промежуток времени или вообще никогда не случится. Из-за этого программа не сможет обрабатывать вызовы уже подключившегося клиента. С другой стороны, если функцию acсeptне вызывать, сервер не сможет обнаружить подключение новых клиентов. Средства для решения этой проблемы есть как у стандартных сокетов, так и у сокетов Windows, и далее мы их рассмотрим. Но существует довольно популярный способ ее решения средствами не библиотеки сокетов, а операционной системы. Он заключается в использовании отдельной нити для обслуживания каждого из клиентов. Каждый раз, когда клиент подключается, функция acceptпередает управление программе, возвращая новый сокет. Здесь сервер может породить новую нить, которая предназначена исключительно для обмена данными с новым клиентом. Старая нить после этого снова вызывает accept для старого сокета, а новая — функции recvи sendдля нового сокета. Такой метод решает заодно и проблемы, связанные с тем, что функции sendи recvтакже могут блокировать работу программы и помешать обмену данными с другими клиентами. В данном случае будет блокирована только одна нить, обменивающаяся данными с одним из клиентов, а остальные нити продолжат свою работу. Далее мы рассмотрим пример сервера, работающего по такой схеме.

Рис 23Последовательность действий клиента и сервера при использовании TCP - фото 20

Рис. 2.3.Последовательность действий клиента и сервера при использовании TCP

То, что функция recvможет возвратить только часть ожидаемого пакета, обычно вызывает трудности, поэтому здесь мы рассмотрим один из вариантов написания функции (назовем ее ReadFromSocket), которая эти проблемы решает (листинг 2.13). Суть этой функции в том, что она вызывает recv до тех пор, пока не будет получено требуемое количество байтов или пока не возникнет ошибка. Тот код, который получает и анализирует приходящие данные, использует уже не recv, a ReadFromSocket, которая гарантирует, что будет возвращено столько байтов, сколько требуется.

Листинг 2.13. Функция ReadFromSocket, читающая из буфера сокета заданное количество байтов

// Функция читает Cnt байтов в буфер Buffer из сокета S

// Учитывается, что может потребоваться несколько операций чтения,

// прежде чем будет прочитано нужное число байтов.

// Возвращает:

// 1 — в случае успешного чтения

// 0 - в случае корректного закрытия соединения удаленной стороной

// -1 — в случае ошибки чтения

function ReadFromSocket(S: TSocket; var Buffer; Cnt: Integer): Integer;

var

Res, Total: Integer;

begin

// Total содержит количество принятых байтов

Total := 0;

// Читаем байты в цикле до тех пор, пока не будет прочитано Cnt байтов

repeat

// На каждой итерации цикла нам нужно прочитать

// не более чем Cnt - Total байтов, т.е. не более

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

Интервал:

Закладка:

Сделать


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

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




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


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


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

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