《Linux网络编程之IO复用循环服务器(共8页).doc》由会员分享,可在线阅读,更多相关《Linux网络编程之IO复用循环服务器(共8页).doc(8页珍藏版)》请在得力文库 - 分享文档赚钱的网站上搜索。
1、精选优质文档-倾情为你奉上1.介绍在前几节,我们介绍了循环服务器,并发服务器. 简单的循环服务器每次只能处理一个请求,即处理的请求是串行的。而并发服务器可以通过创建多个进程或者是线程来并发的处理多个请求。但由于进程或线程的切换会带来一定的开销。而且随着客户端请求的增多,创建的线程或进程的数目也越来越多,开销势必会增加。因此,本文提出了I/O复用的循环服务器。I/O复用的循环服务器创建两个线程,一个是客户端连接处理线程,专门用来处理客户端的连接,当有客户端到来的时候,此线程把客户端的套接字描述符放到一块公共的区域中。另一个是业务处理线程,此线程轮循(select)客户端套接字描述符集合中有没有数
2、据到来,如果有数据到来,那么就进行处理。2. I/O复用循环服务器处理流程socket(.);bind(.);listen(.);pthread_create(.);pthread_join(.);close(.); /关闭服务器套接字连接处理线程:while(1) accept(.); store(.);/存储客户端套接字描述符业务处理线程:while(1)get(.);/取出套接字描述符放到FD_SETselect(.);recv(.);process(.);send(.);close(.);从算法的主要流程可以看出,I/O复用循环服务器只用两个线程,一个是请求业务连接线程,专门处理连接。
3、另一个是业务处理线程,轮循客户端的套接字有没有数据。3. 相关例子服务器;#include #include #include #include #include #include #include #include /*I/O复用循环服务器I/O并发服务器随着客户端的增多,必须增加处理单元,系统的负载会移动多个处理单元的切换上,切换进程或者是线程而I/O复用服务器包括两个线程,一个是业务连接线程,专门处理客户端的连接,另一个是业务请求处理线程,对多个客户端描述符进行一定时间的等待,即select监听多个描述符*/#define PORT 8888#define CLIENTNUM 1024#
4、define BUFFERSIZE 1024#define BACKLOG 10static int connect_hostCLIENTNUM;static int connect_number=0;/连接的客户数static void* handle_connect(void*argv)/业务连接函数,处理客户端的连接,将客户端的套接字描述符加入到连接池中 int ret; int s; int sc; s=*(int*)argv);/服务端套接字描述符 int i=0; struct sockaddr_in client_addr; int len; len=sizeof(struct
5、sockaddr_in); for(;)/监听有没有客户端到来 sc=accept(s,(struct sockaddr*)&client_addr,&len); printf(a client connect,from:%sn,inet_ntoa(client_addr.sin_addr); if(sc0) for(i=0;iCLIENTNUM;i+) if(connect_hosti=-1) connect_hosti=sc; connect_number+; break; /请求业务处理线程static void* handle_request(void*argv) time_t now
6、; char bufferBUFFERSIZE; int size; /设置轮循的时间,每隔1秒 struct timeval tv; tv.tv_sec=1; tv.tv_usec=0; int ret; int i=0; int maxfd; fd_set scanfd; for(;) FD_ZERO(&scanfd);/清空文件描述符集合 /将文件描述符放入文件描述符集合 for(i=0;iCLIENTNUM;i+) if(connect_hosti!=-1) FD_SET(connect_hosti,&scanfd); if(maxfdconnect_hosti) maxfd=conn
7、ect_hosti; /select ret=select(maxfd+1,&scanfd,NULL,NULL,&tv);/监控读文件描述符集,看看是否有数据可读 switch(ret) case -1:/错误 break; case 0:/超时 break; default:/有数据到来 if(connect_number0) break; for(i=0;i0&!strncmp(buffer,TIME,4)/时间请求 memset(buffer,0,BUFFERSIZE); now=time(NULL); sprintf(buffer,%24srn,ctime(&now); send(co
8、nnect_hosti,buffer,strlen(buffer),0); /更新文件描述符数组中的值 connect_hosti=-1; connect_number-; close(connect_hosti);/关闭客户端套接字描述符 break; int main(int argc,char*argv) int ret; int s; struct sockaddr_in server_addr; int i; pthread_t thread2;/两个线程,一个是处理连接,另一个是处理请求 /建立TCP套接字s=socket(AF_INET,SOCK_STREAM,0);memset
9、(connect_host,-1,CLIENTNUM);/将存储套接字描述符的数组为-1if(s0) perror(socket error); return -1;/将地址结构绑定到套接字描述符server_addr.sin_family=AF_INET;server_addr.sin_addr.s_addr=htonl(INADDR_ANY);server_addr.sin_port=htons(PORT);ret=bind(s,(struct sockaddr*)&server_addr,sizeof(struct sockaddr_in);if(ret0) perror(bind er
10、ror); return -1;/监听ret=listen(s,BACKLOG);if(ret0) perror(listen error); return -1; pthread_create(&thread0,NULL,handle_connect,(void*)&s);/处理客户端连接,传递的是服务器的套接字描述符 pthread_create(&thread1,NULL,handle_request,NULL);/handle_request线程回调函数/等待线程结束 for(i=0;i2;i+) pthread_join(threadi,NULL);close(s);客户端:#inc
11、lude #include #include #include #include #include #include #define PORT 8888#define BUFFERSIZE 1024int main(int argc,char*argv)int s;int ret;int size;struct sockaddr_in server_addr;char bufferBUFFERSIZE;s=socket(AF_INET,SOCK_STREAM,0);if(s0) perror(socket error); return -1;bzero(&server_addr,sizeof(
12、server_addr);/将地址结构绑定到套接字server_addr.sin_family=AF_INET;server_addr.sin_port=htons(PORT);server_addr.sin_addr.s_addr=htonl(INADDR_ANY);/连接服务器ret=connect(s,(struct sockaddr*)&server_addr,sizeof(server_addr);if(ret=-1) perror(connect error); return -1;memset(buffer,0,BUFFERSIZE);strcpy(buffer,TIME);si
13、ze=send(s,buffer,strlen(buffer),0);if(size0) perror(send error); return -1;memset(buffer,0,BUFFERSIZE);size=recv(s,buffer,BUFFERSIZE,0);if(size0) perror(recv error); return;printf(%s,buffer);close(s);return 0;运行结果:rootlocalhost 14章服务器模式# ./select-tcpa client connect,from:127.0.0.1rootlocalhost 14章服务器模式# ./circle-tcpc14Sat Feb 18 14:28:10 2012总结:本文主要针对简单循环服务器,并发服务器的不足,介绍了I/O复用的循环服务器,最后给出了实例.专心-专注-专业