Составители:
Рубрика:
ния, не перемещая указатель очереди. Другими словами, при последовательных операциях
чтения будут возвращаться одни и те же данные (точнее, должны возвращаться; обратитесь
ко врезке "Получение фрагментированных пакетов").
•MSG_WAITALL - Сообщение не будет возвращено до тех пор, пока не заполнится указанный
буфер. При отсутствии этого флага возможно получение частично заполненного буфера, по-
скольку
остальные данные еще "в пути". В этом случае программе придется "собирать" их
самостоятельно.
•MSG_DONTWAIT
Запрос к сокету не будет блокирован, если очередь сообщений пуста. Анало-
гичный режим (неблокируемый ввод-вывод) можно также задать в свойствах самого сокета.
Обычно, если данные в очереди отсутствуют, диспетчер очереди ждет до тех пор, пока они не
поступят. А когда этот флаг установлен, функция, запрашивающая данные, немедленно за-
вершается, возвращая
код ошибки EWOULDBLK. (В настоящее время в Linux не поддержи-
вается этот флаг. Чтобы достигнуть требуемого результата, необходимо вызвать функцию
fcntl() с флагом О_NONBLOCK. Это заставит сокет всегда работать в режиме неблокируемо-
го ввода-вывода.)
Получение фрагментированных пакетов
Программа может работать гораздо быстрее, чем сеть. Иногда пакеты приходят по частям, потому
что маршрутизаторы фрагментируют их для ускорения передачи по медленным сетям. Если] в подоб-
ной ситуации вызвать функцию recv(), будет прочитано неполное сообщение. Вот по-| чему даже при
наличии флага MSG_PEEK
функция recv() при последовательных вызовах можете возвращать разные
данные: например, сначала 500 байтов, а затем 750. Для решения подобных проблем предназначен флаг
MSG_WAITALL.
Функция recv() является более гибкой, чем read(). Ниже показано, как прочитать данные из канала
сокета (эквивалентно функции read()):
int bytes_read;
bytes_read = recv(sd, buffer, MAXBUF, 0);
...
А вот как осуществить неразрушающее чтение:
int bytes_read;
bytes_read = recv(sd, buffer, MAXBUF, MSG_PEEK);
...
Можно даже задать режим неразрушающего чтения внеполосных данных:
int bytes read;
bytes_read = recv(sd, buffer, MAXBUF, MSG_OOB | MSG_PEEK);
...
В первом варианте функция просто передает серверу указатель буфера и значение его длины. Во втором
фрагменте информация копируется из очереди, но не извлекается из нее.
Во всех трех фрагментах есть одно преднамеренное упущение. Что если сервер пошлет больше
информации, чем может вместить буфер? В действительности ничего страшного не произойдет, это не
критическая ошибка. Просто программа потеряет те данные, которые не были прочитаны.
Функция recv() возвращает те же коды ошибок, что и функция read(), но есть и дополнения.
•ENOTCONN. Предоставленный дескриптор сокета не связан с одноранговым компьютером или
сервером.
•ENOTSOCK. Предоставленный дескриптор не содержит сигнатуру, указывающую на то, что он
был создан функцией socket ().
Вообще
говоря, функция read() тоже может вернуть эти коды, поскольку на самом деле она про-
веряет, какой дескриптор ей передан, и если это дескриптор сокета, она просто вызывает функцию
recv().
Разрыв соединения
Информация от сервера получена, сеанс прошел нормально — настало время прекращать связь.
Опять-таки, есть два способа сделать это. В большинстве программ используется стандартный систем-
ный вызов close ():
#include <unistd.h>
ния, не перемещая указатель очереди. Другими словами, при последовательных операциях чтения будут возвращаться одни и те же данные (точнее, должны возвращаться; обратитесь ко врезке "Получение фрагментированных пакетов"). •MSG_WAITALL - Сообщение не будет возвращено до тех пор, пока не заполнится указанный буфер. При отсутствии этого флага возможно получение частично заполненного буфера, по- скольку остальные данные еще "в пути". В этом случае программе придется "собирать" их самостоятельно. •MSG_DONTWAIT Запрос к сокету не будет блокирован, если очередь сообщений пуста. Анало- гичный режим (неблокируемый ввод-вывод) можно также задать в свойствах самого сокета. Обычно, если данные в очереди отсутствуют, диспетчер очереди ждет до тех пор, пока они не поступят. А когда этот флаг установлен, функция, запрашивающая данные, немедленно за- вершается, возвращая код ошибки EWOULDBLK. (В настоящее время в Linux не поддержи- вается этот флаг. Чтобы достигнуть требуемого результата, необходимо вызвать функцию fcntl() с флагом О_NONBLOCK. Это заставит сокет всегда работать в режиме неблокируемо- го ввода-вывода.) Получение фрагментированных пакетов Программа может работать гораздо быстрее, чем сеть. Иногда пакеты приходят по частям, потому что маршрутизаторы фрагментируют их для ускорения передачи по медленным сетям. Если] в подоб- ной ситуации вызвать функцию recv(), будет прочитано неполное сообщение. Вот по-| чему даже при наличии флага MSG_PEEK функция recv() при последовательных вызовах можете возвращать разные данные: например, сначала 500 байтов, а затем 750. Для решения подобных проблем предназначен флаг MSG_WAITALL. Функция recv() является более гибкой, чем read(). Ниже показано, как прочитать данные из канала сокета (эквивалентно функции read()): int bytes_read; bytes_read = recv(sd, buffer, MAXBUF, 0); ... А вот как осуществить неразрушающее чтение: int bytes_read; bytes_read = recv(sd, buffer, MAXBUF, MSG_PEEK); ... Можно даже задать режим неразрушающего чтения внеполосных данных: int bytes read; bytes_read = recv(sd, buffer, MAXBUF, MSG_OOB | MSG_PEEK); ... В первом варианте функция просто передает серверу указатель буфера и значение его длины. Во втором фрагменте информация копируется из очереди, но не извлекается из нее. Во всех трех фрагментах есть одно преднамеренное упущение. Что если сервер пошлет больше информации, чем может вместить буфер? В действительности ничего страшного не произойдет, это не критическая ошибка. Просто программа потеряет те данные, которые не были прочитаны. Функция recv() возвращает те же коды ошибок, что и функция read(), но есть и дополнения. •ENOTCONN. Предоставленный дескриптор сокета не связан с одноранговым компьютером или сервером. •ENOTSOCK. Предоставленный дескриптор не содержит сигнатуру, указывающую на то, что он был создан функцией socket (). Вообще говоря, функция read() тоже может вернуть эти коды, поскольку на самом деле она про- веряет, какой дескриптор ей передан, и если это дескриптор сокета, она просто вызывает функцию recv(). Разрыв соединения Информация от сервера получена, сеанс прошел нормально — настало время прекращать связь. Опять-таки, есть два способа сделать это. В большинстве программ используется стандартный систем- ный вызов close (): #include
Страницы
- « первая
- ‹ предыдущая
- …
- 8
- 9
- 10
- 11
- 12
- …
- следующая ›
- последняя »