I/O复用实现单线程并发服务器

来源:互联网 发布:java判断上午下午 编辑:程序博客网 时间:2024/04/28 03:49
/* * ===================================================================================== * *       Filename:  select.c * *    Description:   * *        Version:  1.0 *        Created:  2012年02月22日 22时18分07秒 *       Revision:  none *       Compiler:  gcc * *         Author:  MaZheng (blog.csdn.net/mazheng1989), mazheng19891019@gmail.com *        Company:  Dalian University Of Technology * * ===================================================================================== */#include<stdio.h>#include<string.h>#include<unistd.h>#include<sys/types.h>#include<sys/socket.h>#include<netinet/in.h>#include<stdlib.h>#include<arpa/inet.h>#include<sys/time.h>#definePORT 1234/* port that will be opened */#defineBACKLOG 5/* number of allowed connections */#defineMAXDATASIZE 1000/*  */ struct Client{int fd;char *name;struct sockaddr_in addr;/*client's address information*/char *data;};typedef struct Client CLIENT;void process_cli(CLIENT *client,char *recvbuf,int len);void savedata(char * recvbuf,int len,char *data);int main(){int i,maxi,maxfd,sockfd;int nready;ssize_t n;fd_set rset,allset;int listenfd,connectfd; /*socket descriptors*/struct sockaddr_in server;/*server's address information*//*client's information*/CLIENT client[FD_SETSIZE];char recvbuf[MAXDATASIZE];int sin_size;/*create tcp socket*/if((listenfd=socket(AF_INET,SOCK_STREAM,0))==-1){/*handle exception*/perror("creating socket failed.");exit(1);}int opt=SO_REUSEADDR;setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));bzero(&server,sizeof(server));server.sin_family=AF_INET;server.sin_port=htons(PORT);server.sin_addr.s_addr=htonl(INADDR_ANY);if(bind(listenfd,(struct sockaddr *)&server,sizeof(struct sockaddr))==-1){/*handle exception*/perror("bind() error.");exit(1);}if(listen(listenfd,BACKLOG)==-1){perror("listen() error\n");exit(1);}sin_size=sizeof(struct sockaddr_in);/*initialize for select*/maxfd=listenfd;maxi=-1;for(i=0;i<FD_SETSIZE;i++){client[i].fd=-1;}FD_ZERO(&allset);FD_SET(listenfd,&allset);while(1){struct sockaddr_in addr;rset=allset;nready=select(maxfd+1,&rset,NULL,NULL,NULL);if(FD_ISSET(listenfd,&rset)){/*new client connection *//*accept connection*/if((connectfd=accept(listenfd,(struct sockaddr*)&addr,&sin_size))==-1){perror("accept() error.\n");continue;}/*put new fd to client*/for(i=0;i<FD_SETSIZE;i++){if(client[i].fd<0){client[i].fd=connectfd;//save descriptorclient[i].name=(char *)malloc(MAXDATASIZE);client[i].addr=addr;client[i].data=(char *)malloc(MAXDATASIZE);client[i].name[0]='\0';client[i].data[0]='\0';printf("You got a connection from %s.",inet_ntoa(client[i].addr.sin_addr));break;}}if(i==FD_SETSIZE)printf("too many clients.\n");FD_SET(connectfd,&allset);//add new descriptor to setif(connectfd>maxfd)maxfd=connectfd;if(i>maxi)maxi=i;if(--nready<=0)continue;/*no more readable descriptors*/for(i=0;i<=maxi;i++){/*check all clients for data*/if((sockfd=client[i].fd)<0)continue;if(FD_ISSET(sockfd,&rset)){if((n=recv(sockfd,recvbuf,MAXDATASIZE,0))==0){/*connection closed by client*/close(sockfd);printf("client( %s )closed connection.User's data:%s\n",client[i].name,client[i].data);FD_CLR(sockfd,&allset);client[i].fd=-1;free(client[i].name);free(client[i].data);}else{process_cli(&client[i],recvbuf,n);}if(--nready<=0)break;//no more readable descriptors}}}close(listenfd);}return 0;}void process_cli(CLIENT *client,char *recvbuf,int len){char sendbuf[MAXDATASIZE];recvbuf[len-1]='\0';if(strlen(client->name)==0){//get client's name from clientmemcpy(client->name,recvbuf,len);printf("client's name is %s.\n",client->name);return ;}/*save client's data*/printf("received client ( %s )message:%s\n",client->name,recvbuf);/*save user's data*/savedata(recvbuf,len,client->data);int i1;for( i1=0;i1<len-1;i1++){sendbuf[i1]=recvbuf[len-i1-2];}sendbuf[len-1]='\0';send(client->fd,sendbuf,strlen(sendbuf),0);}void savedata(char *recvbuf,int len,char *data){int start=strlen(data);int i;for( i=0;i<len;i++){data[start+i]=recvbuf[i];}}


原创粉丝点击