Читать книгу 📗 "Основы программирования в Linux - Мэтью Нейл"
Поскольку вы создаете дочерние процессы, но не ждете их завершения, следует сделать так, чтобы сервер игнорировал сигналы
SIGCHLD1. Программа server4.c начинается так же, как последний рассмотренный сервер с важным добавлением директивы
include#include <sys/types.h>#include <sys/socket.h>#include <stdio.h>#include <netinet/in.h><i>#include <signal.h></i>#include <unistd.h>#include <stdlib.h>int main() { int server_sockfd, client_sockfd; int server_len, client_len; struct sockaddr_in server_address; struct sockaddr_in client_address; server_sockfd = socket(AF_INET, SOCK_STREAM, 0); server_address.sin_family = AF_INET; server_address.sin_addr.s_addr = htonl(INADDR_ANY); server_address.sin_port = htons(9734); server_len = sizeof(server_address); bind(server_sockfd, (struct sockaddr *)&server_address, server_len);2. Создайте очередь соединений, игнорируйте подробности завершения дочернего процесса и ждите запросов клиентов:
<i> listen(server_sockfd, 5);</i><i> signal(SIGCHLD, SIG_IGN);</i><i> while(1) {</i><i> char ch;</i><i> printf("server waitingn");</i>3. Примите запрос на соединение:
<i> client_len = sizeof(client_address);</i><i> client_sockfd = accept(server_sockfd,</i><i> (struct_sockaddr*)&client_address, &client_len);</i>4. Вызовите
fork<i> if (fork() == 0) {</i>5. Если вы потомок, то можете читать/писать в программе-клиенте на сокете
client_sockfd<i> read(client_sockfd, &ch, 1);</i><i> sleep(5);</i><i> ch++;</i><i> write(client_sockfd, &ch, 1);</i><i> close(client_sockfd);</i><i> exit(0);</i><i> }</i>6. В противном случае вы должны быть родителем и ваша работа с данным клиентом закончена:
<i> else {</i><i> close(client_socket);</i><i> }</i><i> }</i><i>}</i>Код включает пятисекундную задержку при обработке запроса клиента для имитации вычислений сервера или обращения к базе данных. Если бы вы проделали это в предыдущем сервере, каждое выполнение программы client3 заняло бы пять секунд. С новым сервером вы сможете обрабатывать множественные клиентские программы client3 параллельно с общим затраченным временем, чуть превышающим пять секунд.
$ <b>./server4 &</b>[1] 26566 server waiting$ <b>./client3 & ./client3 & ./client3 & ps x</b>[2] 26581[3] 26582[4] 26583server waitingserver waitingserver waitingPID TTY STAT TIME COMMAND26566 pts/1 S 0:00 ./server426581 pts/1 S 0:00 ./client326582 pts/1 S 0:00 ./client326583 pts/1 S 0:00 ./client326584 pts/1 R+ 0:00 ps x26585 pts/1 S 0:00 ./server426586 pts/1 S 0:00 ./server426587 pts/1 S 0:00 ./server4$ char from server = Вchar from server = Вchar from server = В<b>ps x</b>PID TTY STAT TIME COMMAND26566 pts/1 S 0:00 ./server426590 pts/1 R+ 0:00 ps x[2] Done ./client3[3]- Done ./client3[4]+ Done ./client3$Как это работает
Теперь серверная программа создает новый дочерний процесс для обработки каждого клиента, поэтому вы можете видеть несколько сообщений об ожидании сервера, поскольку основная программа продолжает ждать новые запросы на подключения. В выводе команды
psСерверная программа применяет вызов
forkselect