Как уже говорилось, если буфер для исходящих имеет нулевой размер, то функции send
и sendto
независимо от режима работы сокета отправляют данные непосредственно в сеть. Если же размер этого буфера не равен нулю, при необходимости он может увеличиваться.
В MSDN описаны следующие правила роста буфера:
1. Если объем данных в буфере меньше, чем это задано параметром SO_SNDBUF
, то новые данные копируются в буфер полностью. Буфер при необходимости увеличивается.
2. Если объем данных в буфере достиг или превысил SO_SNDBUF
, но в буфере находятся данные, переданные в результате только одного вызова send
, последующий вызов приводит к увеличению буфера до размера, необходимого, чтобы принять эти данные целиком.
3. Если объем данных в буфере достиг или превысил SO_SENDBUF
, и эти данные оказались в буфере в результате нескольких вызовов send
, то буфер не расширяется. Блокирующий сокет при этом ждет, когда за счет отправки данных в буфере появится место, неблокирующий завершает операцию с ошибкой WSAEWOULDBLOCK
.
Следует отметить, что увеличение размера буфера носит временный характер.
Заметим также, что в ходе наших экспериментов второе правило воспроизвести не удалось. Если предел, заданный параметром SO_SNDBUF
, был достигнут, не удавалось поместить новые данные в буфер независимо от того, были ли имеющиеся данные положены туда одним вызовом send
или несколькими. Впрочем, это могут быть детали реализации, которые различны в разных версиях системы.
Ранее мы упоминали, что UDP допускает широковещательную рассылку (рассылку по адресу 255.255.255.255 и т.п.). Но по умолчанию такая рассылка запрещена. Чтобы разрешить широковещательную рассылку, нужно установить в True
параметр SO_BROADCAST
, относящийся к уровню сокета ( SOL_SOCKET
). Таким образом, вызов функции setsockopt
для разрешения широковещательной рассылки будет выглядеть так, как показано в листинге 2.35.
Листинг 2.35. Включение возможности широковещательной рассылки
var
EnBroad: Integer;
begin
EnBroad := 1;
setsockopt(S, SOL_SOCKET, SO_BROADCAST, PChar(@EnBroad), SizeOf(Integer));
Для запрета широковещательной рассылки через сокет используется тот же код, за исключением того, что переменной EnBroad
следует присвоить ноль.
Последний параметр сокета, который мы рассмотрим, называется SO_LINGER
. Он управляет поведением функции closesocket
. Напомним, что по умолчанию эта функция не блокирует вызвавшую ее нить, а закрывает сокет в фоновом режиме. Параметр SO_LINGER
имеет тип TLinger
, представляющий собой следующую структуру:
TLinger = record
l_onoff: u_short;
l_linger: u_short;
end;
Поле l_onoff
этой структуры показывает, будет ли использоваться фоновый режим закрытия сокета. Нулевое значение показывает, что закрытие выполняется в фоновом режиме, как это установлено по умолчанию (в этом случае поле l_linger
игнорируется). Ненулевое значение показывает, что функция closesocket
не вернет управление вызвавшей ее нити, пока сокет не будет закрыт. В этом случае возможны два варианта: мягкое и грубое закрытие. Мягкое закрытие предусматривает, что перед закрытием сокета все данные, находящиеся в его выходном буфере, будут переданы партнеру. При грубом закрытии данные партнеру не передаются. Поле l_linger
задает время (в секундах), которое дается на передачу данных партнеру. Если за отведенное время данные, находящиеся в выходном буфере сокета, не были отправлены, сокет будет закрыт грубо. Если поле l_linger
будет равно нулю (при ненулевом l_onoff
), сокет всегда будет закрываться грубо. Неблокирующие сокеты рекомендуется закрывать с нулевым временем ожидания или в фоновом режиме, При мягком закрытии неблокирующего сокета не в фоновом режиме, если остались непереданные данные, вызов closesocket
завершится с ошибкой WSAEWOULDBLOCK
, и сокет не будет закрыт. Придется вызывать функцию closesocket
несколько раз до тех пор. пока она не завершится успешно.
Остальные параметры сокета детально описаны в MSDN.
2.1.18. Итоги первого раздела
Мы рассмотрели основные принципы работы со стандартными сокетами. Хотя многое осталось за кадром, того, что здесь было написано, достаточно, чтобы начать создавать разнообразные приложения с использованием сокетов. Для самостоятельного изучения рекомендуется сделать следующее:
□ Для каждой из упоминавшихся здесь функций выяснить, какие ошибки может возвращать WSAGetLastError
в случае неуспешного завершения и что каждая из этих ошибок означает.
Читать дальше
Конец ознакомительного отрывка
Купить книгу