unp_test/select/tcpsrvpoll01.c

89 lines
2.4 KiB
C

#include "unp.h"
#include <limits.h> // for OPEN_MAX
#ifndef OPEN_MAX
#define OPEN_MAX _SC_OPEN_MAX
#endif
int main(int argc, char *argv[])
{
int listenfd, confd, sockfd, maxi, i;
int nready;
ssize_t n;
char buf[MAXLINE];
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, (SA *)&servaddr, sizeof(servaddr));
Listen(listenfd, LISTENQ);
client[0].fd = listenfd;
client[0].events = POLLIN;
for(i = 1; i < OPEN_MAX; i++)
client[i].fd = -1;
maxi = 0;
for(;;) {
nready = Poll(client, maxi + 1, INFTIM);
if(client[0].revents & POLLIN) { // new client connection
clilen = sizeof(cliaddr);
confd = Accept(listenfd, (SA *) &cliaddr, &clilen);
for ( i = 0; i < OPEN_MAX; i++)
if(client[i].fd < 0) {
client[i].fd = confd; // save descriptor
break;
}
if( i == OPEN_MAX)
err_quit("too many clients");
client[i].events = POLLIN;
if( i > maxi)
maxi = i; // max index in client[] array
if(--nready <= 0)
continue; // no more readable descriptor
}
for(i = 0; i <= maxi; i++) { // check all clients for data
if((sockfd = client[i].fd) < 0)
continue;
if(client[i].revents & (POLLIN | POLLERR)) {
if( (n = Read(sockfd, buf, MAXLINE)) < 0) {
if( errno == ECONNRESET) {
// connection closed by client
Close(sockfd);
client[i].fd = -1;
} else {
err_sys("read error");
}
} else if(n == 0) {
// connection closed by client
Close(sockfd);
client[i].fd = -1;
} else {
Writen(sockfd, buf, n);
}
if(--nready <= 0)
break; // no more readable descriptors
}
}
}
}