UNIX: разработка сетевых приложений
UNIX: разработка сетевых приложений читать книгу онлайн
Новое издание книги, посвященной созданию веб-серверов, клиент-серверных приложений или любого другого сетевого программного обеспечения в операционной системе UNIX, — классическое руководство по сетевым программным интерфейсам, в частности сокетам. Оно основано на трудах Уильяма Стивенса и полностью переработано и обновлено двумя ведущими экспертами по сетевому программированию. В книгу включено описание ключевых современных стандартов, реализаций и методов, она содержит большое количество иллюстрирующих примеров и может использоваться как учебник по программированию в сетях, так и в качестве справочника для опытных программистов.
Внимание! Книга может содержать контент только для совершеннолетних. Для несовершеннолетних чтение данного контента СТРОГО ЗАПРЕЩЕНО! Если в книге присутствует наличие пропаганды ЛГБТ и другого, запрещенного контента - просьба написать на почту [email protected] для удаления материала
В листинге 6.3 показана первая половина этой версии сервера.
Листинг 6.3. Сервер TCP, использующий одиночный процесс и функцию select: инициализация
//tcpcliserv/tcpservselect01.c
1 #include "unp.h"
2 int
3 main(int argc, char **argv)
4 {
5 int i, maxi, maxfd, listenfd, connfd, sockfd;
6 int nready, client[FD_SETSIZE],
7 ssize_t n;
8 fd_set rset, allset;
9 char buf[MAXLINE];
10 socklen_t clilen;
11 struct sockaddr_in cliaddr, servaddr;
12 listenfd = Socket(AF_INET, SOCK_STREAM, 0);
13 bzero(&servaddr, sizeof(servaddr));
14 servaddr.sin_family = AF_INET;
15 servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
16 servaddr.sin_port = htons(SERV_PORT);
17 Bind(listenfd, (SA*)&servaddr, sizeof(servaddr));
18 Listen(listenfd, LISTENQ);
19 maxfd = listenfd; /* инициализация */
20 maxi = -1; /* индекс в массиве client[] */
21 for (i = 0; i < FD_SETSIZE; i++)
22 client[i] = -1; /* -1 означает свободный элемент */
23 FD_ZERO(&allset);
24 FD_SET(listenfd, &allset);
12-24
socket
bind
listen
select
Вторая половина функции
main
Листинг 6.4. Сервер TCP, использующей одиночный процесс и функцию select: цикл
//tcpcliserv/tcpservselect01.c
25 for (;;) {
26 rset = allset; /* присваивание значения структуре */
27 nready = Select(maxfd + 1, &rset, NULL, NULL, NULL);
28 if (FD_ISSET(listenfd, &rset)) { /* соединение с новым клиентом */
29 clilen = sizeof(cliaddr);
30 connfd = Accept(listenfd, (SA*)&cliaddr, &clilen);
31 for (i = 0; i < FD_SETSIZE; i++)
32 if (client[i] < 0) {
33 client[i] = connfd; /* сохраняем дескриптор */
34 break;
35 }
36 if (i == FD_SETSIZE)
37 err_quit("too many clients");
38 FD_SET(connfd, &allset); /* добавление нового дескриптора */
39 if (connfd > maxfd)
40 maxfd = connfd; /* для функции select */
41 if (i > maxi)
42 maxi = i; /* максимальный индекс в массиве clientf[] */
43 if (--nready <= 0)
44 continue; /* больше нет дескрипторов, готовых для чтения */
45 }
46 for (i = 0; i <= maxi; i++) { /* проверяем все клиенты на наличие
данных */
47 if ((sockfd - client[i]) < 0)
48 continue;
49 if (FD_ISSET(sockfd, &rset)) {
50 if ((n = Read(sockfd, buf, MAXLINE)) == 0) {
51 /* соединение закрыто клиентом */
52 Close(sockfd);
53 FD_CLR(sockfd, &allset);
54 client[i] = -1;
55 } else
56 Writen(sockfd, line, n);
57 if (--nready <= 0)
58 break; /* больше нет дескрипторов, готовых для чтения */
59 }
60 }
61 }
62 }
26-27
select
28-45
accept
client
for
select
46-60
select