C - Using poll to multiplex between socket(s) and

2019-08-10 08:52发布

问题:

I'm writing a client server application and I'm using poll to multiplex between several client sockets and stdin, where I can insert commands (example: stop the server). I believe the structure (the "logic") of my code is correct, however it's not behaving the way I expect it to:

struct pollfd pfd[NSERVER]; //defined as 10
pfd[0].fd = fileno(stdin);
pfd[0].events = POLLIN;
pfd[1].fd = socktfd; //server bind, listen socket
pfd[1].events = POLLIN;
struct sockaddr_storage remoteaddr; // client address
socklen_t addrlen;
char remoteIP[INET6_ADDRSTRLEN];
addrlen = sizeof remoteaddr;
char buf[1024];     // buffer
int pos=2;  

while(poll(pfd,1,0) >= 0)
{
    if(pfd[0].revents & POLLIN) { //stdin
            //process input and perform command
        }
    if(pfd[1].revents & POLLIN) {
        /* new connection */
        int connsockfd = accept(socktfd, (struct sockaddr *)&remoteaddr,&addrlen);  
        pfd[pos].fd=connsockfd;
    }
    int i=2;
    //Loop through the fd in pfd for events
    while (i<=NSERVER)
    {
        if (pfd[i].revents & POLLIN) {
            int c=recv(pfd[i].fd, buf, sizeof buf, 0);
            if(c<=0) {
                if (c==0)
                {
                /* Client closed socket */
                    close(pfd[i].fd);
                }
            }else
            {//Client sent some data
                c=send(pfd[i].fd,sbuff,z,0);
                if (c<=0)
                {
                    Error;
                }
            free(sbuff);
            }
        }
        i++;
    }
}

I've removed some code inside the recv and send to make the code easier to read. It fails to behave (it just hangs, doesn't accept connections or reacts to input from stdin).

Note: I would prefer to use poll over select, so please don't point to select :-).

Thanks in advance for any assistance.

回答1:

  1. you should set every pfd[i].fd = -1, so they get ignored initially by poll().
  2. poll(pfd, 1, 0) is wrong and should at least be poll(pfd, 2, 0) or even poll(pfd, NSERVER, 0).
  3. while(i<=NSERVER) should be while(i<NSERVER)

Your program probably hangs, because you loop through the pfd array, which is not initialized and containes random values for .fd and .revents, so it wants to send() or recv() on some random FD which might block. Do if(pdf[i].fd < 0) {i++; continue;} in the i<NSERVER loop.

You also don't set pfd[pos].events = POLLIN on newly accepted sockets. Don't set POLLOUT unless you have something to send, because it will trigger almost every time.