多路IO转接服务器也叫做多任务IO服务器。该类型服务器实现的主旨思想是,不在由应用程序自己监视连接,取而代之由内核替应用程序监视文件
主要使用方法有三种
1、select 能监听的文件描述符个数受限于FD_SETSIZE,一般为1024,单纯改变进程打开的文件描述符个数能改变select监听文件个数
2、解决1024以下客户端时使用select是很合适的,但如果连接客户端过多,select采用的是轮询模型,会大大降低服务器响应效率
#include#include #include #include int select(int nfds,fd_set *readfds,fd_set *writefds, fd_set *exceptfds,struct timeval *timeout);
nfds:监控的文件描述符集里最大文件描述符加1,因为此参数会告诉内核检测前多少个文件描述符的状态
readfds:监控有读数据到到文件描述符集合,传入传出参数
writefds:监控写数据到达文件描述符集合,传入传出参数
exceptfds:监控异常发生文件描述符集合,如带外数据到达异常,传入传出参数
timeout:定时阻塞监控时间,3种情况
1、NULL,永远等下去
2、设置timeval,等待固定时间
3、设置timeval里时间均为0,检查描述字后立即返回,轮询
struct timeval{
long tv_sec;
long tv_usec;
};
void FD_CLR(int fd,fd_set *set);//把文件描述符集合里fd清0
int FD_ISSET(int fd,fd_set *set);//测试文件描述符集合里fd是否置1
void FD_SET(int fd,fd_set*set);//把文件描述符集合里fd置1
void FD_ZERO(fd_set *set);//把文件描述符集合里所有位清0
server.c
#include#include #include #include #include #define MAXLINE 80 #define SERV_PORT 6666 int main(argc,argv[]) { int i,maxi,maxfd,listenfd,connfd,sockfd; int nready,client[FD_SETSIZE]; ssize_t n; fd_set rset,allset; char buf[MAXLINE]; char str[INET_ADDRSTRLEN]; socklen_t cliaddr_len; 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)); listen(listenfd,20); maxfd = listenfd; //初始化 maxi = -1; //client[]的下标 for(i=0;i maxfd) {maxfd = connfd;} if(i>maxi) maxi = i; if(--nready == 0) {continue;} } for(i=0;i<=maxi;i++){ if((sockfd = client[i])<0) {continue;} if(FD_ISSET(sockfd,&rset)){ if((n==read(sockfd,buf,MAXLINE))==0){ close(sockfd); FD_CLR(sockfd,&allset); client[i] = -1; }else{ int j; for(j=0;j client.c
#include2 poll函数#include #include #include #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; } #includeint poll(struct pollfd *fds,nfds_t nfds,int timeout); struct pollfd{ int fd; short events; short revents; } server.c
#include#include #include #include #include #incldue #include #define MAXLINE 80 #define SERV_PORT 5000 #define OPEN_MAX 1024 int main (int argc,char *argv[]) { int i,j,maxi,listenfd,connfd,sockfd; int nready; ssize_t n; char buff[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)); listen(listenfd,20); client[0].fd = listenfd; client[0].events = POLLRDNORM; for(i = 1;i maxi) {maxi = i;} if(--nready <= 0) {continus;} } for(i = 1;i cleint.c
#include#include #include #include #define MAXLINE 80 #define SERV_PORT 5000 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; int_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 benn closed.n");} else {write(STDOUT_FILENO,buf,n);} } close(sockfd); return 0; }



