两种并发式服务器的选择

来源:互联网 发布: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
原创粉丝点击