Methods poll the server listens on port array used to store them, so that no polling monitor the entire file descriptor
#include <poll.h> int poll ( struct the pollfd * FDS, nfds_t NFDs, int timeout); struct the pollfd { int FD; / * file descriptor * / Short Events; / * monitored event * / Short the revents; / * event monitoring event condition is satisfied returned * / }; priority data POLLIN normal or band-readable, i.e. POLLRDNORM | POLLRDBAND POLLRDNORM-readable data POLLRDBAND priority with data read POLLPRI high priority data readable POLLOUT normal or band data writable POLLWRNORM data can be written POLLWRBAND priority band data can be written POLLERR error occurred POLLHUP occur pending file descriptor is not a POLLNVAL open nfds monitor how much of the array of file descriptors to be monitored timeout milliseconds to wait - 1 : obstruction, #define INFTIM -1 Linux does not define this macro 0 : return immediately without blocking process > 0 : waiting for a specified number of milliseconds, as the current system accuracy is not enough time in milliseconds, ranging up
If you no longer monitor a file descriptor, can pollfd in, fd is set to -1 , poll no longer monitor this pollfd , the next time you return, the revents set to 0 .
/* server.c */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <netinet/in.h> #include <arpa/inet.h> #include <poll.h> #include <errno.h> #include "wrap.h" #define MAXLINE 80 #define SERV_PORT 6666 #define OPEN_MAX 1024 int main(int argc, char *argv[]) { int i, j, maxi, listenfd, connfd, sockfd; int nready; ssize_t n; char buf[MAXLINE], str[INET_ADDRSTRLEN]; socklen_t clilen; struct pollfd client[OPEN_MAX]; struct sockaddr_in cliaddr, servaddr; listenfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(SERV_PORT); Bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); The Listen (listenfd, 20 is ); Client [ 0 ] = .FD listenfd; Client [ 0 ] = .events POLLRDNORM; / * listenfd ordinary read event listener * / for (I = . 1 ; I <the OPEN_MAX; I ++ ) Client [I] .FD = - . 1 ; / * -1 for Client initialization [] in the remaining element * / Maxi = 0 ; / * Client [] array element effective maximum element index * / for (;;) { nready = poll ( Client, Maxi + . 1- . 1 ); / * blocking * / IF (Client [ 0 ] .revents & POLLRDNORM) { / * client connects to the request * / clilen = the sizeof (cliaddr); connfd = the Accept (listenfd, ( struct the sockaddr *) & cliaddr , & clilen); the printf ( " Received from AT PORT% S% D \ n- " , inet_ntop (AF_INET, & cliaddr.sin_addr, STR, the sizeof (STR)), ntohs (cliaddr.sin_port)); for (I = . 1; I <the OPEN_MAX; I ++ ) { IF (Client [I] .FD < 0 ) { Client [I] .FD = connfd; / * find Client [] in the idle position, storing the returned accept connfd * / BREAK ; } } IF (I == the OPEN_MAX) perr_exit ( " TOO MANY Clients " ); Client [I] .events = POLLRDNORM; / * set just returned connfd, monitoring read event * / IF (I> Maxi) Maxi = I; / *Update Client [] elements in the standard maximum * / IF (--nready <= 0 ) Continue ; / * there are no more ready event, continues back to poll blocking * / } for (I = . 1 ; I <= Maxi; ++ I) { / * detected Client [] * / IF ((Client sockfd = [I] .FD) < 0 ) Continue ; IF (Client [I] & .revents (POLLRDNORM | POLLERR)) { IF ((n-= the Read (sockfd, buf, MAXLINE)) < 0 ) { IF (errno == ECONNRESET) {/* 当收到 RST标志时 */ /* connection reset by client */ printf("client[%d] aborted connection\n", i); Close(sockfd); client[i].fd = -1; } else { perr_exit("read error"); } } else if (n == 0) { /* connection closed by client */ printf("client[%d] closed connection\n", i); Close(sockfd); client[i].fd = -1; } else { for (j = 0; j < n; j++) buf[j] = toupper(buf[j]); Writen(sockfd, buf, n); } if (--nready <= 0) break; /* no more readable descriptors */ } } } return 0; }
client
/* client.c */ #include <stdio.h> #include <string.h> #include <unistd.h> #include <netinet/in.h> #include "wrap.h" #define MAXLINE 80 #define SERV_PORT 6666 int main(int argc, char *argv[]) { struct sockaddr_in servaddr; char buf[MAXLINE]; int sockfd, n; sockfd = Socket(AF_INET, SOCK_STREAM, 0); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; inet_pton(AF_INET, "127.0.0.1", &servaddr.sin_addr); servaddr.sin_port = htons(SERV_PORT); Connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)); while (fgets(buf, MAXLINE, stdin) != NULL) { Write(sockfd, buf, strlen(buf)); n = Read(sockfd, buf, MAXLINE); if (n == 0) printf("the other side has been closed.\n"); else Write(STDOUT_FILENO, buf, n); } Close(sockfd); return 0; }
Also contains wrap.c and wrap.h files in the wrong analysis of the blog,
#include <poll.h>
int poll(struct pollfd *fds, nfds_t nfds, int timeout);
struct pollfd {
int fd; / * file descriptor * /
short events; / * monitoring events * /
short revents; / * monitor events in return to meet the conditions of the event * /
};
POLLIN normal or priority band-readable data , i.e. POLLRDNORM | POLLRDBAND
POLLRDNORM data read
POLLRDBAND priority band-readable data
POLLPRI high priority data is readable
POLLOUT normal or band data writable
POLLWRNORM data can be written
POLLWRBAND Priority band data can be written
POLLERR error
POLLHUP hang occurs
POLLNVAL descriptor is not an open file
nfds monitor how much of the array of file descriptors to be monitored
timeout milliseconds to wait
-1 : obstruction, #define INFTIM -1 Linux does not define this macro
0 : return immediately without blocking process
> 0 : waiting for a specified number of milliseconds, such as the current system time in milliseconds insufficient accuracy, the value upward