Составители:
Рубрика:
int sd;
sd = socket(PF_INET, SOCK_STREAM, 0); /* создание сокета */
/**** Подключение к серверу ****/
if ( (sp = fopen(sd, "r")) == NOLL ) /* преобразуем дескриптор
в формат FILE* */
perror("FILE* conversion failed");
else if ( fscanf(sp, "%*s, %*s, %*s\n", /* читаем данные
из файла */
NAME, Name, ADDRESS, Address,
PHONE, Phone) < 0)
{
perror("fscanf");
...
Только дескрипторы сокетов потокового типа могут быть свободно конвертированы в формат
FILE *. Причина этого проста: в протоколе UDP соединение не устанавливается вовсе — дейтаграммы
просто посылаются и все. Кроме того, потоковые сокеты обеспечивают целостность данных и надежную
доставку сообщений, тогда как доставка дейтаграмм не гарантируется. Применение дейтаграмм подобно
вложению письма в конверт с
адресом, отправляемый по почте: нельзя быть полностью уверенным в
том, что письмо дойдет до адресата. Соединение, имеющее дескриптор типа FILE*, должно быть откры-
тым. Если преобразовать данные в формат дейтаграммы, их можно потерять.
Соединения, с которыми связаны файловые дескрипторы, являются для сетевого программиста
удобным средством анализа поступающих данных. Следует, однако, быть предельно
внимательным:
необходимо проверять все возвращаемые значения, даже у функций fprintf() и fscanf(). Обратите внима-
ние на то, что в показанном выше примере отрицательный код, возвращаемый функцией fscanf (), сигна-
лизирует об ошибке.
Безопасность и надежность сети
Безопасность и надежность—это основные факторы, которые следует учитывать при написании
сетевых приложений. Не забывайте проверять переполнение буферов и коды завершения функций. По-
просите других программистов проверить вашу программу на восприимчивость к произвольным вход-
ным данным. Не пренебрегайте советами экспертов.
Возвращаясь к функции read(), отметим, что чаще всего в результате ее выполнения возникают
такие ошибки.
•EAGAIN.
Задан режим неблокируемого ввода-вывода, а данные недоступны. Эта ошибка означа-
ет, что программа должна вызвать функцию повторно.
•EBADF. Указан неверный дескриптор файла, либо файл не был открыт для чтения. Эта ошибка
может возникнуть, если вызов функции socket () завершился неуспешно или же программа за-
крыла входной поток (канал доступен только для записи
).
• EINVAL. Указанный дескриптор связан с объектом, чтение из которого невозможно.
Функция read() не имеет информации о том, как работает сокет. В Linux есть другая функция,
recv(), которая наряду с чтением данных позволяет контролировать работу сокета:
#include <sys/socket.h>
#include <resolv.h>
int recv(int sd, void *buf, int len, unsigned int flags);
Эта функция принимает такие же параметры, как и функция read(), за исключением флагов. Флаги
можно объединять с помощью операции побитового сложения (флаг1 | флаг2 | ...). Обычно последний
параметр задается равным нулю. Читатели могут поинтересоваться, для чего в таком случае вообще вы-
зывать функцию recv()? He проще ли вызвать функцию read()? Лучше применять функцию recv() — это
может помочь
вам, если впоследствии работа программы усложнится. Да и, вообще говоря, всегда сле-
дует придерживаться какого-то одного стиля.
Ниже перечислены полезные флаги, с помощью которых можно управлять работой сокета.
•MSG_OOB - Обработка внеполосных данных. Применяется для сообщений с повышенным при-
оритетом. Некоторые протоколы позволяют выбирать, с каким приоритетом следует послать
сообщение: обычным
или высоким. Установите этот флаг, чтобы диспетчер очереди искал и
возвращал только внеполосные сообщения (подробно об этом — в главе 10, "Создание устой-
чивых сокетов").
•MSG_PEEK - Режим неразрушающего чтения. Заставляет диспетчер очереди извлекать сообще-
int sd; sd = socket(PF_INET, SOCK_STREAM, 0); /* создание сокета */ /**** Подключение к серверу ****/ if ( (sp = fopen(sd, "r")) == NOLL ) /* преобразуем дескриптор в формат FILE* */ perror("FILE* conversion failed"); else if ( fscanf(sp, "%*s, %*s, %*s\n", /* читаем данные из файла */ NAME, Name, ADDRESS, Address, PHONE, Phone) < 0) { perror("fscanf"); ... Только дескрипторы сокетов потокового типа могут быть свободно конвертированы в формат FILE *. Причина этого проста: в протоколе UDP соединение не устанавливается вовсе — дейтаграммы просто посылаются и все. Кроме того, потоковые сокеты обеспечивают целостность данных и надежную доставку сообщений, тогда как доставка дейтаграмм не гарантируется. Применение дейтаграмм подобно вложению письма в конверт с адресом, отправляемый по почте: нельзя быть полностью уверенным в том, что письмо дойдет до адресата. Соединение, имеющее дескриптор типа FILE*, должно быть откры- тым. Если преобразовать данные в формат дейтаграммы, их можно потерять. Соединения, с которыми связаны файловые дескрипторы, являются для сетевого программиста удобным средством анализа поступающих данных. Следует, однако, быть предельно внимательным: необходимо проверять все возвращаемые значения, даже у функций fprintf() и fscanf(). Обратите внима- ние на то, что в показанном выше примере отрицательный код, возвращаемый функцией fscanf (), сигна- лизирует об ошибке. Безопасность и надежность сети Безопасность и надежность—это основные факторы, которые следует учитывать при написании сетевых приложений. Не забывайте проверять переполнение буферов и коды завершения функций. По- просите других программистов проверить вашу программу на восприимчивость к произвольным вход- ным данным. Не пренебрегайте советами экспертов. Возвращаясь к функции read(), отметим, что чаще всего в результате ее выполнения возникают такие ошибки. •EAGAIN. Задан режим неблокируемого ввода-вывода, а данные недоступны. Эта ошибка означа- ет, что программа должна вызвать функцию повторно. •EBADF. Указан неверный дескриптор файла, либо файл не был открыт для чтения. Эта ошибка может возникнуть, если вызов функции socket () завершился неуспешно или же программа за- крыла входной поток (канал доступен только для записи). • EINVAL. Указанный дескриптор связан с объектом, чтение из которого невозможно. Функция read() не имеет информации о том, как работает сокет. В Linux есть другая функция, recv(), которая наряду с чтением данных позволяет контролировать работу сокета: #include#include int recv(int sd, void *buf, int len, unsigned int flags); Эта функция принимает такие же параметры, как и функция read(), за исключением флагов. Флаги можно объединять с помощью операции побитового сложения (флаг1 | флаг2 | ...). Обычно последний параметр задается равным нулю. Читатели могут поинтересоваться, для чего в таком случае вообще вы- зывать функцию recv()? He проще ли вызвать функцию read()? Лучше применять функцию recv() — это может помочь вам, если впоследствии работа программы усложнится. Да и, вообще говоря, всегда сле- дует придерживаться какого-то одного стиля. Ниже перечислены полезные флаги, с помощью которых можно управлять работой сокета. •MSG_OOB - Обработка внеполосных данных. Применяется для сообщений с повышенным при- оритетом. Некоторые протоколы позволяют выбирать, с каким приоритетом следует послать сообщение: обычным или высоким. Установите этот флаг, чтобы диспетчер очереди искал и возвращал только внеполосные сообщения (подробно об этом — в главе 10, "Создание устой- чивых сокетов"). •MSG_PEEK - Режим неразрушающего чтения. Заставляет диспетчер очереди извлекать сообще-
Страницы
- « первая
- ‹ предыдущая
- …
- 7
- 8
- 9
- 10
- 11
- …
- следующая ›
- последняя »