При работе в блокирующем режиме, для того чтобы не зависала программа, нужно использовать множество потоков. Это неудобно, и драгоценное процессорное время расходуется нерационально.

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

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

ЧтобьГперевести сокет в неблокирующий режим, нужно воспользоваться функцией ioctl socket, которая описывается следующим образом:

function іoct1 socket(
s: TSocket:
cmd- DWORD;
var arg: u_long )• Integer;
stdcall:

Рассмотрим параметры функции ioctl socket:

• s - сокет, режим которого надо изменить;
• cmd - команда, которую необходимо выполнить;

• arg - параметр для команды.

Изменение режима блокирования происходит при указании в качестве второго параметра (команды) константы FI0NBI0. При этом если третий параметр указывает на нулевое значение, то будет использоваться блокирующий режим, в противном случае - неблокирующий.

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

var
s: TSOCKET: iMode: Integer: begin
s := socket(AF_INET, SOCK_STREAM. 0). iMode :" 1; ioctlsocket(s. FI0NBI0. iMode):

end, Теперь все функции приема/передачи и соединения с сервером будут завершаться ошибкой. Это нормальная реакция, и вы должны это учитывать при создании сетевых приложений, работающих в неблокирующем режиме. Если функция ввода-вывода вернула ошибку WSAEW0ULDBL0CK, это не является показателем неправильной работы функции. Все прошло успешно, просто используется неблокирующий режим. Если же действительно произошел сбой, то мы получим ошибку, отличную от WSAEW0ULDBL0CK.

В неблокирующем режиме функция recv не будет дожидаться приема данных, а просто возвратит ошибку WSAEW0ULDBL0CK. Тогда как нам узнать, когда же данные поступили на порт? Некоторые запускают цикл с постоянным вызовом функции recv, пока она не вернет данные. Но это не очень эффективно, потому что происходит блокирование приложения из-за бесконечного цикла (оно перестает реагировать на пользовательский ввод), что еще больше загружает процессор, чем блокирующий режим Конечно же, можно вставить в цикле вызов метода Application.ProcessMessage или убрать все в отдельный поток, но мы теряем все преимущества от использования неблокирующего режима.

4.12. Пример использования UDP-протокола || Оглавление || 4.13.1. Проверка готовности сокета через функцию select


Delphi в шутку и всерьез: что умеют хакеры



Новости за месяц

  • Январь
    2022
  • Пн
  • Вт
  • Ср
  • Чт
  • Пт
  • Сб
  • Вс