Linux网络编程之IO复用循环服务器
1.介绍
在前几节,我们介绍了循环服务器,并发服务器. 简单的循环服务器每次只能处理一个请求,即处理的请求是串行的。而并发服务器可以通过创建多个进程或者是线程来并发的处理多个请求。但由于进程或线程的切换会带来一定的开销。而且随着客户端请求的增多,创建的线程或进程的数目也越来越多,开销势必会增加。因此,本文提出了I/O复用的循环服务器。I/O复用的循环服务器创建两个线程,一个是客户端连接处理线程,专门用来处理客户端的连接,当有客户端到来的时候,此线程把客户端的套接字描述符放到一块公共的区域中。另一个是业务处理线程,此线程轮循(select)客户端套接字描述符集合中有没有数据到来,如果有数据到来,那么就进行处理。
2. I/O复用循环服务器处理流程
socket(...);
bind(...);
listen(...);
pthread_create(...);
pthread_join(..);
close(...); //关闭服务器套接字
连接处理线程:
while(1){
? accept(...);
? store(...);//存储客户端套接字描述符
}
业务处理线程:
while(1){
?get(...);//取出套接字描述符放到FD_SET
?select(...);
?recv(....);
?process(...);
?send(...);
?close(....);
}
从算法的主要流程可以看出,I/O复用循环服务器只用两个线程,一个是请求业务连接线程,专门处理连接。另一个是业务处理线程,轮循客户端的套接字有没有数据。
3. 相关例子
服务器;
#include #include #include #include #include #include #include #include /**I/O复用循环服务器I/O并发服务器随着客户端的增多,必须增加处理单元,系统的负载会移动多个处理单元的切换上,切换进程或者是线程而I/O复用服务器包括两个线程,一个是业务连接线程,专门处理客户端的连接,另一个是业务请求处理线程,对多个客户端描述符进行一定时间的等待,即select监听多个描述符**/#define PORT 8888#define CLIENTNUM 1024#define BUFFERSIZE 1024#define BACKLOG 10static int connect_host[CLIENTNUM];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 sockaddr_in);?? for(;;){//监听有没有客户端到来???? sc=accept(s,(struct sockaddr*)&client_addr,&len);???? printf("a client connect,from:%s\n",inet_ntoa(client_addr.sin_addr));??? ????? if(sc>0){??? ??? ?for(i=0;i