1

FD_SETSIZE (非常に大きい可能性があります) を使用する代わりに、ファイル記述子の最大数を毎回追跡するにはどうすればよいですか? これまでのところ、コードは次のとおりです (Beginning Linux Programming, 2nd Edition から適応):

#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <sys/time.h>
#include <sys/ioctl.h>
#include <unistd.h>

#define SERVER_PORT 9734
#define ALLOWED_CLIENTS INADDR_ANY
#define BACKLOG 5
#define DELAY 0

int main()
{
    int server_sockfd, client_sockfd;
    socklen_t server_len, client_len;
    struct sockaddr_in server_address, client_address;
    int result;
    fd_set readfds, testfds;

    server_sockfd = socket(AF_INET, SOCK_STREAM, 0);
    server_address.sin_family = AF_INET;
    server_address.sin_addr.s_addr = htonl(ALLOWED_CLIENTS);
    server_address.sin_port = htons(SERVER_PORT);
    server_len = sizeof(server_address);
    bind(server_sockfd, (struct sockaddr *)&server_address, server_len);

    listen(server_sockfd, BACKLOG);
    FD_ZERO(&readfds); /* Initialise readfds fd_set struct */
    FD_SET(server_sockfd, &readfds); /* Initialise readfds to handle input from server_sockfd */

    while(1) {
        char ch;
        int fd;
        int nread;

        testfds = readfds;
        printf("Server waiting...\n");
        /* Wait indefinitely for client request (input) using testfds */
        result = select(FD_SETSIZE, &testfds, (fd_set *)0, (fd_set *)0, (struct timeval *)0);

        if(result < 1) {
            perror("Server 5");
            exit(1);
        }

        /* At this stage, activity of a client trying to connect has been found.
         * We will find which descriptor it is on by checking each in turn. */
         for(fd = 0; fd < FD_SETSIZE; fd++)
         {
             if(FD_ISSET(fd, &testfds)) { /* If activity occurs on the given file descriptor... */

                    if(fd == server_sockfd) { /* If activity occurs on server_sockfd, it must be
                                               * a request for a new connection */
                        client_len = sizeof(client_address);

                        /* Extract connection request - set client_sockfd equal to this */
                        client_sockfd = accept(server_sockfd, (struct sockaddr *)&client_address, &client_len);

                        /* Add client_sockfd to the descriptor set */
                        FD_SET(client_sockfd, &readfds);
                        printf("    -Added client (fd %d)\n", fd);
                    }
                    else
                    {
                        ioctl(fd, FIONREAD, &nread); /* Find out how much data needs to be read in */

                        if(nread == 0) { /* No data left - finished with this client */
                            close(fd);
                            FD_CLR(fd, &readfds);
                            printf("    -Removed client (fd %d)\n", fd);
                        }
                        else {
                            read(fd, &ch, 1); /* Carry out the server's actual function */
                            sleep(DELAY);
                            printf("    -Serving client (fd %d)\n", fd);
                            ch++;
                            write(fd, &ch, 1);
                        }
                    }
                }
            }
        }
}

この本は、これにより効率が大幅に低下することは理にかなっており、接続されている最大の fd 番号を追跡するために変数を使用する必要があると述べていますが、これを実装する方法がわかりません。実験に何年も費やしました。前もって感謝します。

4

1 に答える 1

2

たとえば、コードにまたはint maxfdが含まれるたびに調整する変数が必要です。この質問への回答には、maxfd を適切に調整する例が含まれています。FD_SET()FD_CLR()

コメントが示唆するのとは異なり、「the」(これは?) variable を作成する必要はないと思いますstatic。poll と epoll に関するコメントは正しいですが、select の使用方法を知っていることも役に立ちます。

于 2013-06-17T07:36:15.560 に答える