Linux网络编程服务器模型选择之并发服务器(下)
2014-03-23 13:58
393 查看
前面两篇文章(参见)分别介绍了循环服务器和简单的并发服务器网络模型,我们已经知道循环服务器模型效率较低,同一时刻只能为一个客户端提供服务,而且对于TCP模型来说,还存在单客户端长久独占与服务器的连接,无法再响应其他连接,对于前面介绍的并发服务器模型是比较简单的,比如由于预先分配了固定进程数目,就导致无法动态调整等问题。在前面我们也提到了对accept函数的处理是区分不同服务器模型的一个重要依据,当然UDP服务器并不需要accept函数,因此本次主要介绍TCP的高级并发模型。按照对accept的不同处理,接下来主要介绍以下几种并发模型:
单客户端单进程,统一accept :服务器主进程等待客户端连接,一旦有连接到来,就创建一个进程用于响应;
单客户端单线程,统一accept :服务器主进程等待客户端连接,一旦有连接到来,就创建一个线程用于响应;
单客户端单线程,各自accept :预先分配多个线程,在每一个线程里都独自等待客户端的连接并响应(注意accept需要互斥访问);
单客户端单线程,各自accept --server端程序
单客户端单进程,统一accept :服务器主进程等待客户端连接,一旦有连接到来,就创建一个进程用于响应;
单客户端单线程,统一accept :服务器主进程等待客户端连接,一旦有连接到来,就创建一个线程用于响应;
单客户端单线程,各自accept :预先分配多个线程,在每一个线程里都独自等待客户端的连接并响应(注意accept需要互斥访问);
并发模型伪代码
/* 单客户端单进程,统一accept */ /* 服务器主进程 */ socket(); bind(); listen(); while(1) { accept(); fork();//子进程 } close(); //关闭服务器端套接字 /* 服务器子进程1 */ recv(); process(); send(); close();//关闭客户端套接字 /* 服务器子进程2(同上) */ ..................
/* 单客户端单线程,统一accept */ /* 服务器主进程 */ socket(); bind(); listen(); while(1) { accept(); pthread_create(); //创建响应线程 } close();//关闭服务器端套接字 /* 服务器线程1 */ recv(); process(); send(); close();//关闭客户端套接字 /* 服务器线程2(同上) */ ..................
/* 单客户端单线程,各自accept */ /* 服务器主进程 */ socket(); bind(); listen(); pthread_create();//创建多个线程分别等待客户端连接 pthread_join();//等待线程结束 close();//关闭服务器端套接字 /* 服务器线程1 */ mutex_lock()//互斥锁 accept(); mutex_unlock(); recv(); process(); send(); close();//客户端套接字 /* 服务器线程2(同上) */ ..................
一个高级并发服务器模型的例子
单客户端单进程,统一accept server端程序
/* 单客户端单进程,统一accept --server端程序*/ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <time.h> #include <string.h> #include <stdio.h> #define BUFFLEN 1024 #define SERVER_PORT 12348 #define BACKLOG 5 static void handle_request(int s_c) { time_t now; char buff[BUFFLEN]; int n = 0; memset(buff, 0, BUFFLEN); n = recv(s_c, buff, BUFFLEN,0); if(n > 0 && !strncmp(buff, "TIME", 4)) { memset(buff, 0, BUFFLEN); now = time(NULL); sprintf(buff, "%24s\r\n",ctime(&now)); send(s_c, buff, strlen(buff),0); } close(s_c); /*关闭客户端*/ } static void handle_connect(int s_s) { int s_c; /*客户端套接字文件描述符*/ struct sockaddr_in from; /*客户端地址*/ int len = sizeof(from); /*主处理过程*/ while(1) { s_c = accept(s_s, (struct sockaddr*)&from, &len);/*接收客户端连接*/ if(s_c > 0)/*客户端成功连接,创建进程进行数据处理*/ { if(fork() > 0) /*父进程*/ { close(s_c); /*关闭父进程的客户端连接套接字*/ } else { handle_request(s_c);/*处理连接请求*/ } } } } int main(int argc, char *argv[]) { int s_s; /*服务器套接字文件描述符*/ struct sockaddr_in local; /*本地地址*/ /*建立TCP套接字*/ s_s = socket(AF_INET, SOCK_STREAM, 0); /*初始化地址*/ memset(&local, 0, sizeof(local)); local.sin_family = AF_INET;/*AF_INET协议族*/ local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/ local.sin_port = htons(SERVER_PORT);/*服务器端口*/ /*将套接字文件描述符绑定到本地地址和端口*/ int err = bind(s_s, (struct sockaddr*)&local, sizeof(local)); err = listen(s_s, BACKLOG);/*侦听*/ /*处理客户端连接*/ handle_connect(s_s); close(s_s); return 0; }
单客户端单进程,统一accept server端程序
单客户端单进程,统一accept server端程序 #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <time.h> #include <string.h> #include <pthread> #include <stdio.h> #define BUFFLEN 1024 #define SERVER_PORT 12348 #define BACKLOG 5 static void *handle_request(void *argv) { int s_c = *((int*)argv); time_t now; char buff[BUFFLEN]; int n = 0; memset(buff, 0, BUFFLEN); n = recv(s_c, buff, BUFFLEN,0); if(n > 0 && !strncmp(buff, "TIME", 4)) { memset(buff, 0, BUFFLEN); now = time(NULL); sprintf(buff, "%24s\r\n",ctime(&now)); send(s_c, buff, strlen(buff),0); } close(s_c); /*关闭客户端*/ } static void handle_connect(int s_s) { int s_c; /*客户端套接字文件描述符*/ struct sockaddr_in from; /*客户端地址*/ int len = sizeof(from); pthread_t thread_do; /*主处理过程*/ while(1) { s_c = accept(s_s, (struct sockaddr*)&from, &len);/*接收客户端连接*/ if(s_c > 0)/*客户端成功连接,创建线程进行数据处理*/ { int err = pthread_create(&thread_do,NULL,handle_request,(void*)&s_c; } } } int main(int argc, char *argv[]) { int s_s; /*服务器套接字文件描述符*/ struct sockaddr_in local; /*本地地址*/ s_s = socket(AF_INET, SOCK_STREAM, 0);/*建立TCP套接字*/ /*初始化地址*/ memset(&local, 0, sizeof(local)); local.sin_family = AF_INET;/*AF_INET协议族*/ local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/ local.sin_port = htons(SERVER_PORT);/*服务器端口*/ /*将套接字文件描述符绑定到本地地址和端口*/ int err = bind(s_s, (struct sockaddr*)&local, sizeof(local)); err = listen(s_s, BACKLOG);/*侦听*/ /*处理客户端连接*/ handle_connect(s_s); close(s_s); return 0; }
单客户端单线程,各自accept --server端程序
/** 单客户端单线程,各自accept --server端程序 */ #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <time.h> #include <string.h> #include <stdio.h> #include <pthread> #define BUFFLEN 1024 #define SERVER_PORT 12348 #define BACKLOG 5 #define CLIENT_NUM 3 pthread_mutex_t g_lock = PTHREAD_MUTEX_INTIALIZER; static void *handle_request(void *argv) { int s_s = *((int*)argv); //服务器端套接字 struct sockaddr_in from; /*客户端地址*/ int len = sizeof(from); int s_c = -1; //客户端套接字 for( ; ; ) { time_t now; char buff[BUFFLEN]; int n = 0; memset(buff, 0, BUFFLEN); pthread_mutex_lock(&g_lock); s_c = accept(s_s,(struct sockaddr*)&from, &len); pthread_mutex_unlock(&g_lock); n = recv(s_c, buff, BUFFLEN,0); if(n > 0 && !strncmp(buff, "TIME", 4)) { memset(buff, 0, BUFFLEN); now = time(NULL); sprintf(buff, "%24s\r\n",ctime(&now)); send(s_c, buff, strlen(buff),0); } close(s_c); /*关闭客户端*/ } return NULL; } static void handle_connect(int s_s) { int s_s = s; pthread_t thread_do[CLIENT_NUM]; for(int i=0; i<CLIENT_NUM;++i) { int err = pthread_create(&thread_do[i],NULL,handle_request,(void*)&s_s; } //等待线程结束 for(int i=0; i<CLIENT_NUM;++i) pthread_join(thread_do[i],NULL); } int main(int argc, char *argv[]) { int s_s; /*服务器套接字文件描述符*/ struct sockaddr_in local; /*本地地址*/ s_s = socket(AF_INET, SOCK_STREAM, 0);/*建立TCP套接字*/ /*初始化地址*/ memset(&local, 0, sizeof(local)); local.sin_family = AF_INET;/*AF_INET协议族*/ local.sin_addr.s_addr = htonl(INADDR_ANY);/*任意本地地址*/ local.sin_port = htons(SERVER_PORT);/*服务器端口*/ /*将套接字文件描述符绑定到本地地址和端口*/ int err = bind(s_s, (struct sockaddr*)&local, sizeof(local)); err = listen(s_s, BACKLOG);/*侦听*/ handle_connect(s_s);/*处理客户端连接*/ close(s_s); return 0; }
相关文章推荐
- Linux网络编程服务器模型选择之并发服务器(上)
- Linux网络编程服务器模型选择之并发服务器(上)
- Linux网络编程服务器模型选择之并发服务器(下)
- linux网络编程:并发服务器的模型
- linux网络编程之并发服务器的三种实现模型 (超级经典)
- Linux网络编程服务器模型选择之IO复用循环并发服务器
- Linux网络编程服务器模型选择之循环服务器
- Linux网络编程——并发服务器模型
- Linux网络编程服务器模型选择之IO复用循环并发服务器
- windows下并发I/O服务器模型对比(五)
- 【并发服务器系列】2 select模型
- LINUX环境并发服务器的三种实现模型
- 常见多线程并发服务器编程模型
- LINUX环境并发服务器的三种实现模型
- Linux网络编程--9. 服务器模型 非常好 (http://www.fanqiang.com)
- 【Unix 网络编程】服务器网络编程模型——多进程并发模型
- linux网络编程多进程并发服务器
- 并发服务器系列】3 epoll模型 - 邓维 - 博客园
- 高并发服务器开发--网络模型
- Linux网络编程之高级并发服务器