#include <poll.h>
int poll(struct pollfd *fdarray, unsigned long nfds, int timeout)
返回:若有就绪描述符则为其数目,若超时为0,若出错为-1
struct pollfd {
int fd;
short evernts;
short revents;
}
tcpservpoll.c
#include "unp.h"
#include <limits.h>
#define OPEN_MAX 1024 /* linux 2.x之后limits.h没有定义 OPEN_MAX 宏 */
int main(int argc, char *argv[])
{
int i, maxi, listenfd, connfd, sockfd;
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 = POLLRDNORM;
for (i = 1; i < OPEN_MAX; i++)
client[i].fd = -1;
maxi = 0;
for (;;){
printf("waitinsg poll\n");
nready = poll(client, maxi + 1, -1);
printf("nready = %d\n", nready);
if (client[0].revents & POLLRDNORM)
{
printf("new client connection\n");
clilen = sizeof(cliaddr);
connfd = accept(listenfd, (SA*)&cliaddr, &clilen);
for(i = 1; i < OPEN_MAX; i++)
{
if (client[i].fd < 0)
{
printf("new clients %d\n", i);
client[i].fd = connfd;
break;
}
}
if (i == OPEN_MAX)
{
printf("too many clients\n");
return 0;
}
client[i].events = POLLRDNORM;
if (i > maxi)
{
maxi = i;
}
if (--nready <=0)
continue;
}
for (i = 1; i <= maxi; i++)
{
if ((sockfd = client[i].fd) < 0)
continue;
if (client[i].revents & (POLLRDNORM | POLLERR))
{
if ((n= read(sockfd, buf, MAXLINE)) < 0 )
{
if (errno == ECONNRESET)
{
close(sockfd);
client[i].fd = -1;
}
else
{
printf("read error\n");
}
}
else if (n == 0)
{
close(sockfd);
client[i].fd = -1;
}
else
{
write(sockfd, buf, n);
}
if (nready <= 0)
break;
}
}
}
return 0;
}
测试客户端代码 :
#include <stdio.h>
#include <string.h>
#include <linux/filter.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <net/if.h>
#include <netinet/in.h>
#define SERV_IP "127.0.0.1"
#define SERV_PORT 9877
#define MAXLINE 254
#define max(a,b) (a)>=(b)?(a):(b)
int str_cli (FILE * fp, int sockfd)
{
int maxfdp1, stdineof;
fd_set rset;
char buf[MAXLINE];
int n;
stdineof = 0;
for(;;)
{
if (stdineof == 0)
FD_SET(fileno(fp), &rset);
FD_SET(sockfd, &rset);
maxfdp1 = max(fileno(fp), sockfd) +1;
select(maxfdp1, &rset, NULL, NULL, NULL);
if (FD_ISSET(sockfd, &rset))
{
if ((n = read(sockfd, buf, MAXLINE)) == 0)
{
if (stdineof == 1)
return;
else
{
printf("strcli:server terminated prematurely\n");
}
}
write(fileno(stdout),buf,n);
}
if (FD_ISSET(fileno(fp), &rset))
{
if ((n = read(fileno(fp), buf, MAXLINE)) == 0)
{
stdineof = 1;
shutdown(sockfd, SHUT_WR);
FD_CLR(fileno(fp), &rset);
continue;
}
write(sockfd, buf, n);
}
}
return 0;
}
void cli_init( int *sockfd)
{
struct sockaddr_in servaddr;
*sockfd = socket(AF_INET, SOCK_STREAM, 0);
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(SERV_PORT);
inet_pton(AF_INET, SERV_IP, &servaddr.sin_addr);
connect(*sockfd, (struct sockaddr*) &servaddr, sizeof(servaddr));
printf("connect\n");
return;
}
int main(int argc, char *argv[])
{
int sockfd;
cli_init( &sockfd);
str_cli(stdin, sockfd);
return 0;
}