两种并发式服务器的选择
来源:互联网 发布:python alpha策略框架 编辑:程序博客网 时间:2024/05/16 19:16
对于有多个客户端对服务器发起连接请求时,建立起连接的时候,这时服务器就得选择使用并发式的服务器去接受客户端,如众所周知的,一般的并发服务器都是利用创建线程来实现的,但是当我们有成百上千个客户端连接时,这时服务器得判断到底是哪个客户端发送的信息,所以就得在线程中不停得切换线程,这样一来就消耗太多的CPU资源,造成了许多额外的系统开销,所以有第二种方法,就是在服务器accept()函数接受连接请求之前,设立一个相当于监听的函数,系统API函数select(),它不需要线程实现,即就不用造成额外的开销,节省CPU的资源:具体介绍看如下实例程序
第一种:线程实现并发式服务器(之前写过,故客户端的代码就没必要写出来了)
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <netdb.h>#define PORT 3333#define MAX_SIZE 1024void * read_msg(void *arg){ int n_read; int new_fd = *((int *)arg); char buffer[MAX_SIZE]; printf("new_fd = %d\n",new_fd); while(1) { memset(buffer,0,sizeof(buffer));n_read = read(new_fd,buffer,sizeof(buffer));if(n_read < 0){ perror("recv client msg error!\n"); exit(1);}if(n_read == 0){ printf("client is close!!\n"); close(new_fd); pthread_exit(NULL);}buffer[n_read] = '\0';printf("recv msg:%s\n",buffer); }}int main(){ int sockfd; int new_fd; struct sockaddr_in server_addr; struct sockaddr_in client_addr; int n_read; int ser_size; int opt = 1; char buffer[MAX_SIZE]; pthread_t id; if((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { perror("socket error!\n");exit(1); } printf("socket success.............!\n"); if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)) < 0) { perror("set socket option error!\n");exit(1); } bzero(&server_addr,0); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); if(bind(sockfd,(struct sockaddr *)&server_addr,sizeof server_addr) < 0) { perror("bind error!\n");exit(1); } printf("bind success.............!\n"); listen(sockfd,5); printf("listen success.............!\n"); printf("accepting..................!\n"); while(1) { ser_size = sizeof client_addr; if((new_fd = accept(sockfd,(struct sockaddr *)&client_addr,&ser_size)) < 0) { perror("accept error!\n"); exit(1); } printf("accept success.................!\n"); pthread_create(&id,NULL,read_msg,&new_fd); } return 0;}
第二种方法:调用select()函数
#include <stdlib.h>#include <stdio.h>#include <errno.h>#include <string.h>#include <netdb.h>#include <sys/types.h>#include <netinet/in.h>#include <sys/socket.h>#include<unistd.h>#include<arpa/inet.h>#include<ctype.h>#define portnumber 8000#define MAX_LINE 80int main(void){int lfd;int cfd;int sfd;int rdy;struct sockaddr_in sin;struct sockaddr_in cin;int client[FD_SETSIZE]; int maxi;int maxfd; fd_set rset;fd_set allset;socklen_t addr_len; char buffer[MAX_LINE];int i;int n;int len;int opt = 1; char addr_p[20];bzero(&sin,sizeof(struct sockaddr_in)); sin.sin_family=AF_INET; sin.sin_addr.s_addr=htonl(INADDR_ANY); sin.sin_port=htons(portnumber); if((lfd=socket(AF_INET,SOCK_STREAM,0))==-1) {fprintf(stderr,"Socket error:%s\n\a",strerror(errno));exit(1);} printf("socket!\n");setsockopt(lfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));if(bind(lfd,(struct sockaddr *)(&sin),sizeof(struct sockaddr))==-1){fprintf(stderr,"Bind error:%s\n\a",strerror(errno));exit(1);} printf("bind!\n");if(listen(lfd,20)==-1){fprintf(stderr,"Listen error:%s\n\a",strerror(errno));exit(1);} printf("listen!\n"); printf("Accepting connections .......\n");maxfd = lfd; maxi = -1;for(i = 0;i < FD_SETSIZE;i++){ client[i] = -1;} FD_ZERO(&allset); FD_SET(lfd,&allset); while(1){rset = allset; printf("selecting!\n");rdy = select(maxfd + 1, &rset, NULL, NULL, NULL);printf("selected!\n");if(FD_ISSET(lfd, &rset)){addr_len = sizeof(sin); printf("accepting!\n");if((cfd=accept(lfd,(struct sockaddr *)(&cin),&addr_len))==-1){fprintf(stderr,"Accept error:%s\n\a",strerror(errno));exit(1);}printf("accepted!\n"); for(i = 0; i<FD_SETSIZE; i++){ //printf("%d\t",client[i]);if(client[i] <= 0){client[i] = cfd; break;}}if(i == FD_SETSIZE){printf("too many clients");exit(1);}FD_SET(cfd, &allset); if(cfd > maxfd) {maxfd = cfd;}if(i > maxi){maxi = i;}if(--rdy <= 0) {continue;}}for(i = 0;i< FD_SETSIZE;i++){if((sfd = client[i]) < 0){continue;}if(FD_ISSET(sfd, &rset)){printf("reading!\n");n = read(sfd,buffer,MAX_LINE);printf("%s\n",buffer);printf("read!\n");if(n == 0){printf("the other side has been closed. \n");fflush(stdout); close(sfd);FD_CLR(sfd, &allset); client[i] = -1;}else{inet_ntop(AF_INET, &cin.sin_addr, addr_p, sizeof(addr_p));addr_p[strlen(addr_p)] = '\0';printf("Client Ip is %s, port is %d\n",addr_p,ntohs(cin.sin_port));if(n == 1){exit(1);}} if(--rdy <= 0){break;}}}}close(lfd); return 0;}
0 0
- 两种并发式服务器的选择
- 并发式TCP服务器的设计
- 并发式面向对象网络服务器的实现
- 并发式IO的解决方案
- TCP并发式服务器编程实现
- windows网络编程之并发式服务器
- linux tcp并发式服务器应用SELECT函数编写实例源代码(转载)
- linux tcp并发式服务器应用SELECT函数编写实例源代码
- 2、并发式(concurrent)服务器 一个连接对应一个线程(进程)
- linux tcp并发式服务器应用SELECT函数编写实例源代码(转载)
- 有名管道+多进程最基本的并发式的通信
- 一种基于TCP/IP协议的网络编程模式(并发式多线程编程)
- 并发式IO的解决方案---非阻塞式、多路复用和异步通知(异步IO)
- ]浅谈几种服务器端模型——多线程并发式(线程池)
- 浅谈几种服务器端模型——多线程并发式(线程池)
- 浅谈几种服务器端模型——多进程并发式
- 浅谈几种服务器端模型——多线程并发式(线程池)
- Stackless Python并发式编程介绍
- docker 相关命令
- jvm与GC 基本 三
- 设计模式之适配器模式
- String详解, String和CharSequence区别, StringBuilder和StringBuffer的区别 (String系列之1)
- ZHA Coordinator 如何控制ZLL Light/Philips Hue Light
- 两种并发式服务器的选择
- 机房收费系统---软件需求说明书
- 重学多线程开发,学习并发思路
- VS2013常用快捷键
- nginx+php+mysql+yaf+git服务器搭建记录
- cassandra 3.x官方文档(3)---gossip通信协议及故障检测与恢复
- PAT 1075. PAT Judge (排序,比较烦)
- 11.日期和时间
- ZIGBEE中Profile、Cluster和Attribute关系