Recv как прочесть всю страницу в си
Перейти к содержимому

Recv как прочесть всю страницу в си

Recv как прочесть всю страницу в си

int recv(int s , void * buf , size_t len , int flags );

int recvfrom(int s , void * buf , size_t len , int flags , struct sockaddr * from , socklen_t * fromlen );

int recvmsg(int s , struct msghdr * msg , int flags );

ОПИСАНИЕ

Если параметр from не равен NULL , а сокет не является ориентированным на соединения, то адрес отправителя в сообщении не заполняется. Аргумент fromlen передается по ссылке, в начале инициализируется размером буфера, связанного с from , а при возврате из функции содержит действительный размер адреса.

Вызов recv обычно используется только на соединенном сокете (см. connect (2)) и идентичен вызову recvfrom с параметром from , установленным в NULL .

Все три функции возвращают длину сообщения при успешном завершении. Если сообщение слишком длинное и не поместилось в предоставленный буфер, лишние байты могут быть отброшены, в зависимости от типа сокета, на котором принимаются сообщения (см. socket (2)).

Если на сокете не доступно ни одного сообщения, то обсуждаемые функции ожидают их прибытия, если сокет не помечен как неблокирующий (см. fcntl (2)), в противном случае возвращается значение -1, а внешняя переменная errno устанавливается в значение EAGAIN . Все эти функции обычно возвращают уже доступные данные вплоть до запрошенного объема, и не ждут, пока появятся данные полной запрошенной длины.

Системные вызовы select (2) или poll (2) можно использовать для определения появления новых данных.

Аргумент flags системного вызова recv формируется с помощью объединения логической операцией ИЛИ одного или более нижеследующих значений: MSG_OOB Этот флаг запрашивает прием внепотоковых данных, которые в противном случае не были бы получены в обычном потоке данных. Некоторые протоколы помещают данные повышенной срочности в начало обычной очереди данных, и поэтому этот флаг не может использоваться с такими протоколами. MSG_PEEK Этот флаг заставляет выбрать данные из начала очереди, но не удалять их оттуда. Таким образом, последующий вызов функции вернет те же самые данные. MSG_WAITALL Этот флаг просит подождать, пока не придет полное запрошенное количество данных. Однако, этот вызов все равно может вернуть меньше данных, чем было запрошено, если был пойман сигнал, произошла ошибка или разрыв соединения, или если начали поступать данные другого типа, не того, который был сначала. MSG_TRUNC Возвращает реальную длину пакета, даже если она была больше, чем предоставленный буфер. Этот флаг можно использовать только с пакетными протоколами. MSG_ERRQUEUE Получить пакет из очереди ошибок. MSG_NOSIGNAL Этот флаг отключает возникновение сигнала SIGPIPE на потоковых сокетах, если другая сторона вдруг исчезает. MSG_ERRQUEUE Указание этого флага позволяет получить из очереди ошибок сокета накопившиеся ошибки. Каждая ошибка передается во вспомогательном сообщении, чей тип зависит от протокола (для IPv4 этим типом является IP_RECVERR ). Пользователь должен предоставить буфер достаточной длины. См. cmsg (3) и ip (7), где приведена дополнительная информация. Содержимое исходного пакета, который привел к ошибке, передается в виде обычных данных с помощью msg_iovec . Исходный адрес назначения датаграммы, которая вызвала ошибку, передается с помощью msg_name . Для локальных ошибок адрес не передается (это можно выяснить, проверив поле cmsg_len структуры cmsghdr ). Для ошибок при приеме в msghdr устанавливается MSG_ERRQUEUE . После того, как ошибка передана программе, следующая ошибка в очереди ошибок становится ожидающей ошибкой и передается программе при следующей операции на сокете.

Ошибка хранится в структуре sock_extended_err : ee_errno содержит значение errno для ожидающей ошибки. ee_origin источник происхождения ошибки. Смысл остальных полей зависит от протокола. SOCK_EE_OFFENDER возвращает указатель на адрес сетевого объекта, породившего ошибку. Если этот адрес неизвестен, то член sa_family структуры sockaddr содержит значение AF_UNSPEC , а прочие поля структуры не определены. Содержимое пакета, вызвавшего ошибку, передаются в виде обычных данных. Для локальных ошибок адрес не передается (это можно проверить, взглянув на член cmsg_len структуры cmsghdr ). При приеме ошибок в структуре msghdr установлен флаг MSG_ERRQUEUE . После того, как ошибка была передана, следующая в очереди ошибка используется для перегенерации ошибки сокета, и именно она будет возвращена при следующей операции с этим сокетом.

Системный вызов recvmsg использует структуру msghdr для того, чтобы минимизировать количество непосредственно передаваемых параметров. Эта структура определена в <sys/socket.h> так:

Здесь msg_name и msg_namelen задают адрес назначения, если сокет не соединен; в параметре msg_name можно передать NULL , если имена не требуются или вообще нежелательны. Поля msg_iov и msg_iovlen описывают точки scatter-gather, что обсуждается в readv (2). Поле msg_control , имеющее длину msg_controllen , указывает на буфер для других сообщений, связанных с управлением протоколов, или на буфер для разнообразных вспомогательных данных. Когда вызывается recvmsg , в параметре msg_controllen должна находиться длина доступного буфера, чей адрес передается в msg_control ; при успешном завершении в этом параметре будет находиться длина последовательности контрольных сообщений.

Сообщения имеют такую форму:

К вспомогательным данным нужно обращаться только с помощью макросов, определенных в cmsg (3).

Например, Linux использует этот механизм вспомогательных данных для того, чтобы передавать через Unix-сокеты расширенные ошибки, флаги IP и файловые дескрипторы.

Поле msg_flags в msghdr устанавливается при возврате из recvmsg (2). Оно может содержать несколько флагов: MSG_EOR означает "конец записи": возвращенные данные заканчивают запись (обычно используется вместе с сокетами типа SOCK_SEQPACKET ). MSG_TRUNC означает, что хвостовая часть датаграммы была отброшена, потому что датаграмма была больше, чем предоставленный буфер. MSG_CTRUNC означает, что часть управляющих данных была отброшена из-за недостатка места в буфере вспомогательных данных. MSG_OOB возвращается для индикации получения внепотоковых данных. MSG_ERRQUEUE означает, что были получены не данные, а расширенное сообщение об ошибке из очереди ошибок сокета. MSG_DONTWAIT Разрешает неблокирующий режим. Если операция могла бы привести к блокировке, возвращается EAGAIN (этот режим можно также включить с помощью O_NONBLOCK и функции F_SETFL системного вызова fcntl (2)).

Recv как прочесть всю страницу в си

#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
struct sockaddr *src_addr, socklen_t *addrlen);
ssize_t recvmsg(int sockfd, struct msghdr *msg, int flags);

ОПИСАНИЕ

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

Если на сокете не доступно ни одного сообщения, то обсуждаемые вызовы ожидают их прибытия, если сокет не помечен как неблокирующий (см. fcntl(2)), в противном случае возвращается значение -1, а внешняя переменная errno устанавливается в значение EAGAIN или EWOULDBLOCK. Все эти вызовы обычно сразу возвращают все доступные данные вплоть до запрошенного объема, а не ждут, пока появятся данные полной запрошенной длины.

Для определения появления новых данных в сокете приложение может использовать select(2), poll(2) или epoll(7).

Аргумент флагов

Ошибка передаётся в виде структуры sock_extended_err:

В ee_errno содержится значение errno для ожидающей ошибки. В ee_origin содержится источник происхождения ошибки. Смысл остальных полей зависит от протокола. Макрос SOCK_EE_OFFENDER возвращает указатель на адрес сетевого объекта, породившего ошибку. Если этот адрес неизвестен, то поле sa_family структуры sockaddr содержит значение AF_UNSPEC, а прочие поля структуры sockaddr не определены. Содержимое пакета, вызвавшего ошибку, передаётся в виде обычных данных. Для локальных ошибок адрес не передаётся (это можно выяснить, проверив поле cmsg_len структуры cmsghdr). Для ошибок при приёме устанавливается флаг MSG_ERRQUEUE в msghdr. После того, как ошибка передана программе, следующая ошибка в очереди ошибок становится ожидающей ошибкой и передается программе при следующей операции на сокете. MSG_OOB Этот флаг запрашивает приём внеполосных данных, которые в противном случае не были бы получены в обычном потоке данных. Некоторые протоколы помещают данные повышенной срочности в начало очереди с обычными данными, и поэтому этот флаг не может использоваться с такими протоколами. MSG_PEEK Этот флаг заставляет выбрать данные из начала очереди приёма, но не удалять их оттуда. Таким образом, последующий вызов вернёт те же самые данные. MSG_TRUNC (начиная с Linux 2.2) Для «сырых» данных (AF_PACKET), дейтаграмм Интернета (начиная с Linux 2.4.27/2.6.8), netlink (начиная с Linux 2.6.22) и дейтаграмм UNIX (начиная с Linux 3.4) возвращает реальную длину пакета или дейтаграммы, даже если она была больше, чем предоставленный буфер.

Описание использования с потоковым сокетами Интернета смотрите в tcp(7).

MSG_WAITALL (начиная с Linux 2.2) Этим флагом включается блокирование операции до полной обработки запроса. Однако, этот вызов всё равно может вернуть меньше данных, чем было запрошено, если был пойман сигнал, произошла ошибка или разрыв соединения, или если начали поступать данные другого типа, не того, который был сначала.

recvfrom()

Если значение src_addr не равно NULL, и в нижележащем протоколе используется адрес источника сообщения, то адрес источника помещается в буфер, указанный в src_addr. В этом случае addrlen является аргументом-результатом. Перед вызовом ему должно быть присвоено значение длины буфера, связанного с src_addr. При возврате addrlen обновляется и содержит действительный размер адреса источника. Возвращаемый адрес обрезается, если предоставленный буфер слишком мал; в этом случае addrlen будет содержать значение большее, чем указывалось в вызове.

Если вызывающему адрес источника не нужен, то значение src_addr и addrlen должно быть равно NULL.

recvfrom(fd, buf, len, flags, NULL, 0));

recvmsg()

Поле msg_name указывает на выделенный вызывающим буфер, который используется для возврата адреса источника, если сокет не соединён. Вызывающий должен указать в msg_namelen размер этого буфера перед вызовом; при успешном выполнении вызова в msg_namelen будет содержаться длина возвращаемого адреса. Если приложению не нужно знать адрес источника, то в msg_name можно указать NULL.

В полях msg_iov и msg_iovlen описываются место приёма/передачи, обсуждаемые в readv(2).

Поле msg_control длиной msg_controllen указывает на буфер для других сообщений, связанных с управлением протоколом или на буфер для разнообразных вспомогательных данных. При вызове recvmsg() в поле msg_controllen должен указываться размер доступного буфера, чей адрес передан в msg_control; при успешном выполнении вызова в этом параметре будет находиться длина последовательности контрольных сообщений.

Сообщения имеют следующий вид:

К вспомогательным данным нужно обращаться только с помощью макросов, определённых в cmsg(3).

Например, этот механизм вспомогательных данных используется в Linux для передачи расширенных ошибок, флагов IP и файловых дескрипторов через доменные сокеты Unix.

При возврате из recvmsg() устанавливается значение поля msg_flags в msghdr. Оно может содержать несколько флагов:

MSG_EOR означает конец записи: возвращённые данные заканчивают запись (обычно используется вместе с сокетами типа SOCK_SEQPACKET). MSG_TRUNC означает, что хвостовая часть датаграммы была отброшена, потому что датаграмма была больше, чем предоставленный буфер. MSG_CTRUNC означает, что часть управляющих данных была отброшена из-за недостатка места в буфере вспомогательных данных. MSG_OOB возвращается для индикации получения внеполосных данных. MSG_ERRQUEUE означает, что были получены не данные, а расширенное сообщение об ошибке из очереди ошибок сокета.

ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ

Когда ответная сторона потока выполняет корректное отключение (shutdown), то возвращается 0 (обычный возврат «конец файла»).

В датаграмных сокетах некоторых доменов (например, доменах UNIX и Internet) разрешены датаграммы нулевой длины. При получении такой датаграммы возвращается значение 0.

Также значение 0 может возвращаться, если запрошенное количество принимаемых байт из потокового сокета равно 0.

ОШИБКИ

СООТВЕТСТВИЕ СТАНДАРТАМ

В POSIX.1 описаны только флаги MSG_OOB, MSG_PEEK и MSG_WAITALL.

ЗАМЕЧАНИЯ

В соответствие с POSIX.1 поле msg_controllen структуры msghdr должно иметь тип socklen_t, но в настоящее время в glibc оно имеет тип size_t.

В recvmmsg(2) можно найти информацию о специальном системном вызове Linux, который можно использовать для приёма нескольких датаграмм за один вызов.

14.3. Функции recv и send

Эти две функции аналогичны стандартным функциям read и write, но для них требуется дополнительный аргумент.

ssize_t recv(int sockfd, void *buff, size_t nbytes, int flags);

ssize_t send(int sockfd, const void *buff, size_t nbytes, int flags);

Обе функции возвращают: количество прочитанных или записанных байтов в случае успешного выполнения, -1 в случае ошибки

Первые три аргумента функций recv и send совпадают с тремя первыми аргументами функций read и write. Аргумент flags либо имеет нулевое значение, либо формируется в результате применения операции логического ИЛИ к константам, представленным в табл. 14.1.

Таблица 14.1. Аргумент flags для функций ввода-вывода

flags Описание recv send MSG_DONTROUTE He искать в таблице маршрутизации • MSG_DONTWAIT Только эта операция является неблокируемой • • MSG_OOB Отправка или получение внеполосных данных • MSG_PEEK Просмотр приходящих сообщений • MSG_WAITALL Ожидание всех данных •

? MSG_DONTROUTE. Этот флаг сообщает ядру, что получатель находится в нашей сети, и поэтому не нужно выполнять поиск в таблице маршрутизации. Дополнительную информацию об этом свойстве мы приводим при описании параметра сокета SO_DONTROUTE (см. раздел 7.5). Это свойство можно включить для одной операции вывода с флагом MSG_DONTROUTE или для всех операций вывода данного сокета, используя указанный параметр сокета.

? MSG_DONTWAIT. Этот флаг указывает, что отдельная операция ввода-вывода является неблокируемой. Таким образом, отпадает необходимость включать флаг отсутствия блокировки для сокета, выполнять операцию ввода-вывода и затем выключать флаг отсутствия блокировки. Неблокируемый ввод-вывод мы опишем в главе 15 вместе с включением и выключением флага отсутствия блокировки для всех операций ввода-вывода через сокет.

Этот флаг введен в Net/3 и может не поддерживаться в некоторых системах.

? MSG_OOB. С функцией send этот флаг указывает, что отправляются внеполосные данные. В случае TCP в качестве внеполосных данных должен быть отправлен только 1 байт, как показано в главе 21. С функцией recv этот флаг указывает на то, что вместо обычных данных должны читаться внеполосные данные.

? MSG_PEEK. Этот флаг позволяет нам просмотреть пришедшие данные, готовые для чтения, при этом после выполнения функции recv или recvfrom данные не сбрасываются (при повторном вызове этих функций снова возвращаются уже просмотренные данные). Подробнее мы поговорим об этом в разделе 14.7.

? MSG_WAITALL. Этот флаг был впервые введен в 4.3BSD Reno. Он сообщает ядру, что операция чтения должна выполняться до тех пор, пока не будет прочитано запрашиваемое количество байтов. Если система поддерживает этот флаг, мы можем опустить функцию readn (см. листинг 3.9) и заменить ее макроопределением

#define readn(fd, ptr, n) recv(fd, ptr, n, MSG_WAITALL)

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

Существуют дополнительные флаги, используемые протоколами, отличными от TCP/IP. Например, транспортный уровень OSI основан на записях (а не на потоке байтов, как TCP), и для операций вывода поддерживает флаг MSG_EOR, задающий конец логической записи.

С аргументом flags связана одна фундаментальная проблема: он передается по значению и не является аргументом типа «значение-результат». Следовательно, он может использоваться только для передачи флагов от процесса к ядру. Ядро не может передать флаги обратно процессу. Это не представляет проблемы с TCP/IP, поскольку очень редко бывает необходимо передавать флаги обратно процессу от ядра. Но когда к 4.3BSD Reno были добавлены протоколы OSI, появилась необходимость возвращать процессу флаг MSG_EOR при операции ввода. В 4.3BSD Reno было принято решение оставить аргументы для общеупотребительных функций (recv и recvfrom) как есть и изменить структуру msghdr, которая используется с функциями recvmsg и sendmsg. В разделе 14.5 мы увидим, что в эту структуру был добавлен целочисленный элемент msg_flags, и поскольку структура передается по ссылке, ядро может изменить флаги, содержащиеся в этом элементе, по завершении функции. Это значит также, что если процессу необходимо, чтобы флаги изменялись ядром, процесс должен вызвать функцию recvmsg вместо вызова функции recv или recvfrom.

Данный текст является ознакомительным фрагментом.

Продолжение на ЛитРес

Читайте также

Функции

Функции Существует мнемоническое правило: функции не должны по объему кода превышать двух экранов текста и иметь больше десяти локальных переменных. Каждая функция должна выполнять одно действие, но делать это хорошо. Не вредно разбить функцию на последовательность

Иерархический принцип обмена (send-иерархия)

Иерархический принцип обмена (send-иерархия) В обмене сообщениями есть одна вещь, которая, возможно, не является очевидной — это необходимость следовать строгой иерархии обмена. Означает это то, что два потока никогда не должны посылать сообщения друг другу; наоборот, они

16.5.1. Функции

16.5.1. Функции Интерфейс termios определяет несколько функций. Все они объявлены в &lt;termios.h&gt;. Четыре из них являются обслуживающими функциями для переносимого манипулирования структурой struct termios; остальные представляют собой системные вызовы. Функции, начинающиеся с cf,

Функции

Функции Функция — это особым образом написанный и оформленный фрагмент кода JavaScript, который можно вызвать из любого Web-сценария на данной Web-странице (повторно используемый код, как его часто называют). Так что, если какой-то фрагмент кода встречается в нескольких местах

Функции GMP

Функции GMP ПодразделыФункции Введение Функции этого вида позволяют работать с целыми числами повышенной точности определенного формата используя библиотеку GNU MP.Эта библиотека не входит в стандартный пакет PHP. Загрузить коды библиотеки и документацию по ней можно на

Функции

Функции Использование функций делает сопровождение своих скриптов проще. Проще говоря, это хороший способ разделить программу на более мелкие куски. Функция выполняет определенное действие и может возвращать то значение, какое вы пожелаете. Прежде чем продолжать, я

4.5.3. Функции, которые создают новые конфигурации из существующих 4.5.3.1. Функции геометрии, которые производят новые конфигурации

4.5.3. Функции, которые создают новые конфигурации из существующих 4.5.3.1. Функции геометрии, которые производят новые конфигурации Раздел "4.5.2. Функции Geometry" обсуждает несколько функций, которые создают новые конфигурации из

Функции

Функции Excel – серьезная программа для вычислений, одним из главных достоинств которой является множество встроенных функций. Это обширная тема, достойная если не книги, то главы в многотомном руководстве. Рассмотрим ее кратко – ровно настолько, чтобы вы могли далее

ФУНКЦИИ

ФУНКЦИИ Введение Функция — это совокупность объявлений и операторов, предназначенная для выполнения некоторой отдельной задачи. Количество функций в программе не ограничивается. Любая программа на языке Си содержит, по крайней мере, одну функцию, так называемую

Функции

Функции В табл. П3.1–П3.5 представлено описание наиболее часто используемых функций.Таблица П3.1. Булевые функции Функция Описание boolean boolean(object) Явным образом преобразует объект, который ей передается в булевый тип boolean not(boolean) Выполняет логическое

1.5 Функции

1.5 Функции Функция – это именованная часть программы, к которой можно обращаться из других частей программы столько раз, сколько потребуется. Рассмотрим программу, печатающую степени числа 2:extern float pow(float, int); //pow() определена в другом местеmain() (* for (int i=0; i«10; i++) cout „« pow(2,i) ««

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *