случае ошибки возвращается -1, а переменная errno устанавливается следующим образом:

♦ EBADF — неверный дескриптор сокета:

♦ ENOTSOCK — указанный дескриптор является файлом, а не сокетом;

♦ EFAULT — нет доступа к адресу, на который указывает указатель optval, то есть данный адрес находится за пределами видимости приложения.

Функция getsockopt() возвращает значение параметра. Кроме вышеперечисленных параметров, функция getsockopt() может использовать следующие параметры:

♦ SO_ERROR — возвращает номер ошибки (будет в возвращаемом значении);

♦ SO_TYPE — возвращает тип сокета.

Рассмотрим небольшой пример работы с опциями сокетов. Мы установим размер буфера TCP.

#include 'sock.h'

#include 'stdio.h'

main() {

 int sd; /* дескриптор сокета */

 int optval; /* значение опции */

 int optlen; /* длина optval */

 int new_buffsize = 8192; /* новый размер буфера */

 /* создаем сокет */

 sd = socket(AF_INET, SOCK_STREAM, 0);

 /* считывание длины буфера TCP */

 optlen = sizeof(optval);

 getsockopt(sd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen);

 printf('Size of send buffer %d ', optval);

 getsockopt(sd, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);

 printf('Size of recv buffer %d ', optval);

 /* изменяем длину буфера */

 setsockopt(sd, SOL_SOCKET, SO_RCVBUF,

  &new_buffsize, sizeof(new_buffsize));

 setsockopt(sd, SOL_SOCKET, SO_SNDBUF,

  &new_buffsize, sizeof(new_buffsize));

 /* выводим измененную информацию */

 getsockopt(sd, SOL_SOCKET, SO_SNDBUF, &optval, &optlen);

 printf('New size of send buffer %d ', optval);

 getsockopt(sd, SOL_SOCKET, SO_RCVBUF, &optval, &optlen);

 printf('New size of recv buffer %d ', optval);

}

27.3.10. Сигналы и сокеты

С сокетами связаны три сигнала:

♦ SIGIO — сокет готов к вводу/выводу. Сигнал посылается процессу, который связан с сокетом;

♦ SIGURG — сокет получил экспресс-данные (мы их использовать не будем, поэтому особо останавливаться на них нет смысла);

♦ SIGPIPE — запись в сокет больше невозможна. Сигнал посылается процессу, связанному с сокетом. Например, функция write() вызывает сигнал SIGPIPE, если удаленный процесс завершен или связь по сети невозможна.

Пример обработки сигнала SIGPIPE приведен ниже.

Листинг 27.6. Обработка сигнала SIGPIPE

#include 'sock.h'

#include <signal.h>

/* обработчик сигнала SIGPIPE */

sigpipe_handler() {

 err_quit('Получен SIGPIPE ');

}

main() {

 int sock; /* дескриптор сокета */

 /* установка обработчика сигнала SIGPIPE */

 signal(SIGPIPE, sigpipe_handler);

 /* работа с сокетом */

}

27.3.11. Мультиплексирование

В этой главе мы рассматривали пример программы-сервера, обрабатывающей запросы только от одного клиента. На практике все выглядит намного сложнее: серверу приходится одновременно обрабатывать запросы многих клиентов. Для мультиплексирования запросов клиентов используется системный вызов select(). Этот вызов использует, например, суперсервер xinetd.

Листинг 27.7. Мультиплексирование запросов

#include 'sock.h'

#include <sys/time.h>

main() {

 int sock; /* дескриптор исходного сокета */

 int new_sock; /* дескриптор, полученный с помощью accept */

 int retval; /* возвращаемое значение */

 struct sockaddr_in server; /* адрес сокета */

 fd_set readv; /* переменная для select */

 fd_set writev; /* переменная для select */

 struct timeval tout; /* тайм-аут для select */

 /* бесконечный цикл ожидания */

 for (;;) {

  /* процесс ждет операцию ввода-вывода на сокете;

     одновременно можно ждать и другие операции */

  FD_ZERO(&readv);

  FD_ZERO(&writev);

  FD_SET(sock, &readv);

  FD_SET(sock, &writev);

  tout.tv_sec = 10; /* 10 секунд */

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату