Самьюэл Алекс
Шрифт:
для приема запросов. */
memset(&socket_address, 0, sizeof(socket_address));
socket_address.sin_family = AF_INET;
socket_address.sin_port = port;
socket_address.sin_addr = local_address;
/* Привязка сокета к этому адресу. */
rval =
bind(server_socket, &socket_address,
sizeof(socket_address));
if (rval != 0)
system_error("bind");
/* Перевод сокета в режим приема запросов. */
rval = listen(server_socket, 10);
if (rval != 0)
system_error("listen");
if (verbose) {
/* В режиме развернутых сообщений отображаем адрес и порт,
с которыми работает сервер. */
socklen_t address_length;
/* Нахождение адреса сокета. */
address_length = sizeof(socket_address);
rval =
getsockname(server_socket, &socket_address, &address_length);
assert(rval == 0);
/* Вывод сообщения. Номер порта должен быть преобразован
из сетевого (обратного) порядка следования байтов
в серверный (прямой). */
printf("server listening on %s:%d\n",
inet_ntoa(socket_address.sin_addr),
(int)ntohs(socket_address.sin_port));
}
/* Бесконечный цикл обработки запросов. */
while (1) {
struct sockaddr_in remote_address;
socklen_t address_length;
int connection;
pid_t child_pid;
/* Прием запроса. Эта функция блокируется до тех пор, пока
не поступит запрос. */
address_length = sizeof(remote_address);
connection = accept(server_socket, &remote_address,
&address_length);
if (connection == -1) {
/* Функция завершилась неудачно. */
if (errno == EINTR)
/* Функция была прервана сигналом. Повторная попытка. */
continue;
else
/* Что-то случилось. */
system_error("accept");
}
/* Соединение установлено. Вывод сообщения, если сервер
работает в режиме развернутых сообщений. */
if (verbose) {
socklen_t address_length;
/* Получение адреса клиента. */
address_length = sizeof(socket_address);
rval =
getpeername(connection, &socket_address, &address_length);
assert(rval == 0);
/* Вывод сообщения. */
printf("connection accepted from %s\n",
inet_ntoa(socket_address.sin_addr));
}
/* Создание дочернего процесса для обработки запроса. */
child_pid = fork;
if (child_pid == 0) {
/* Это дочерний процесс. Потоки stdin и stdout ему не нужны,
поэтому закрываем их. */
close(STDIN_FILENO);
close(STDOUT_FILENO);
/* Дочерний процесс не должен работать с серверным сокетом,
поэтому закрываем его дескриптор. */
close(server_socket);
/* Обработка запроса. */
handle_connection(connection);
/* Обработка завершена. Закрываем соединение и завершаем
дочерний процесс. */