Шрифт:
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);
Создание прослушиваемого сокета и инициализация функции select
12-24
Этапы создания прослушиваемого сокета те же, что и раньше: вызов функций socket
, bind
и listen
. Мы инициализируем структуры данных при том условии, что единственный дескриптор, который мы с помощью функции select
выберем, изначально является прослушиваемым сокетом. Вторая половина функции
main
показана в листинге 6.4. Листинг 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);