♦ SIGIO — сокет готов к вводу/выводу. Сигнал посылается процессу, который связан с сокетом;
♦ SIGURG — сокет получил экспресс-данные (мы их использовать не будем, поэтому особо останавливаться на них нет смысла);
♦ SIGPIPE — запись в сокет больше невозможна. Сигнал посылается процессу, связанному с сокетом. Например, функция write вызывает сигнал SIGPIPE, если удаленный процесс завершен или связь по сети невозможна.
Пример обработки сигнала SIGPIPE приведен ниже.
Листинг 27.6. Обработка сигнала SIGPIPE
#include "sock.h"
#include <signal.h>
/* обработчик сигнала SIGPIPE */
sigpipe_handler {
err_quit("Получен SIGPIPE \n");
}
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 секунд */
retval = select(sock+1, &readv, &writev, 0, &to);
/* если select возвращает нулевое значение, значит тайм-аут */
if (retval == 0) {
err_ret("timeout");
continue;
}
/* в противном случае, ищем соответствующий дескриптор */
if ( (FD_ISSET(sock, &readv)) || (FD_ISSET(sock, &writev))) {