Читаем Linux API. Исчерпывающее руководство полностью

Если в потоковом сокете включить параметр TCP_CORK, то весь его вывод будет буферизироваться в одном TCP-сегменте, пока не произойдет одно из следующих событий: достижение максимального размера сегмента, выключение параметра TCP_CORK, закрытие сокета или завершение интервала в 200 миллисекунд с момента записи первого «закупоренного» байта. (Использование времени ожидания гарантирует, что данные будут переданы, даже если приложение забудет отключить TCP_CORK.)

Для включения и отключения параметра TCP_CORK служит системный вызов setsockopt() (см. раздел 57.9). Применение этого режима продемонстрировано на примере следующего кода, в котором реализован наш гипотетический HTTP-сервер (мы намеренно опустили проверку ошибок):

int optval;

/* Включаем TCP_CORK для 'sockfd' — последующий TCP-вывод закупоривается,

пока этот параметр не будет выключен. */

optval = 1;

setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, sizeof(optval));

write(sockfd…); /* Записываем HTTP-заголовки */

sendfile(sockfd…); /* Отправляем содержимое страницы */

/* Отключаем TCP_CORK для 'sockfd' — закупоренный вывод начинает

передаваться в виде единого TCP-сегмента. */

optval = 0

setsockopt(sockfd, IPPROTO_TCP, TCP_CORK, sizeof(optval));

Мы могли бы избежать потенциальной передачи двух сегментов, создав в нашем приложении единый буфер данных, который можно было бы передавать с помощью одного вызова write(). (Как вариант, можно было бы воспользоваться вызовом writev(), чтобы объединить два разных буфера в одну групповую операцию.) Но если мы хотим выполнять передачу с нулевым копированием, которую обеспечивает вызов sendfile(), в сочетании с включением заголовка в первый сегмент передаваемого файла, то для этого нужно использовать параметр TCP_CORK.

В разделе 57.3 мы отмечали: флаг MSG_MORE обеспечивает похожее на TCP_CORK поведение, но для отдельных системных вызовов. Это не всегда является преимуществом. Мы можем включить для сокета параметр TCP_CORK и затем запустить программу, которая направляет вывод в унаследованный файловый дескриптор, не имея никакого представления о том, что использует данный параметр. Для сравнения, флаг MSG_MORE требует непосредственного изменения исходного кода программы.

В FreeBSD существует параметр, похожий на TCP_CORK; он называется TCP_NOPUSH.

57.5. Получение адреса сокета

Системные вызовы getsockname() и getpeername() возвращают локальный адрес, к которому привязан сокет, и, соответственно, адрес удаленного сокета на другом конце соединения.

#include

int getsockname(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

int getpeername(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

Оба вызова возвращают 0 при успешном завершении или -1 при ошибке

В обоих вызовах аргумент sockfd обозначает файловый дескриптор, ссылающийся на сокет, а addr — указатель на буфер подходящего размера, применяемый для возвращения структуры с адресом сокета. Размер и тип этой структуры зависят от домена сокета. С помощью аргумента addrlen возвращается итоговый результат. Перед вызовом он должен быть равен размеру буфера, на который указывает addr; при возвращении он содержит количество байтов, записанных в этот буфер.

Функция getsockname() возвращает семейство адресов сокета и адрес, к которому привязан данный сокет. Это может пригодиться, если он был привязан другой программой (например, inetd(8)), а его файловый дескриптор был сохранен на протяжении работы вызова exec().

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

• после вызова connect() или listen() для TCP-сокета, который ранее не был привязан к адресу с помощью операции bind();

• при первом вызове sendto() для UDP-сокета, ранее не привязанного к адресу;

• после вызова bind(), если в качестве номера порта (sin_port) был указан 0. В этом случае данный вызов определяет IP-адрес сокета, а ядро выбирает для него номер динамического порта.

Системный вызов getpeername() возвращает адрес удаленного сокета на другом конце соединения. Это может пригодиться в ситуации, когда серверу нужно получить адрес клиента, инициировавшего соединение. Данную информацию можно также получить при выполнении вызова accept(); но если сервер был запущен программой, которая вызвала accept() (например, inetd), то не сможет получить сведения об адресе, несмотря на наличие файлового дескриптора сокета.

Использование функций getsockname() и getpeername() продемонстрировано в листинге 57.3. Эта программа задействует функции, которые мы определили в листинге 55.9, для выполнения следующих шагов.

Перейти на страницу:

Похожие книги

1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
1С: Управление торговлей 8.2
1С: Управление торговлей 8.2

Современные торговые предприятия предлагают своим клиентам широчайший ассортимент товаров, который исчисляется тысячами и десятками тысяч наименований. Причем многие позиции могут реализовываться на разных условиях: предоплата, отсрочка платежи, скидка, наценка, объем партии, и т.д. Клиенты зачастую делятся на категории – VIP-клиент, обычный клиент, постоянный клиент, мелкооптовый клиент, и т.д. Товарные позиции могут комплектоваться и разукомплектовываться, многие товары подлежат обязательной сертификации и гигиеническим исследованиям, некондиционные позиции необходимо списывать, на складах периодически должна проводиться инвентаризация, каждая компания должна иметь свою маркетинговую политику и т.д., вообщем – современное торговое предприятие представляет живой организм, находящийся в постоянном движении.Очевидно, что вся эта кипучая деятельность требует автоматизации. Для решения этой задачи существуют специальные программные средства, и в этой книге мы познакомим вам с самым популярным продуктом, предназначенным для автоматизации деятельности торгового предприятия – «1С Управление торговлей», которое реализовано на новейшей технологической платформе версии 1С 8.2.

Алексей Анатольевич Гладкий

Финансы / Программирование, программы, базы данных