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

/* * ===================================================================================== * * 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> #define PORT 1234 /* port that will be opened */ #define BACKLOG 5 /* number of allowed connections */ #define MAXDATASIZE 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 descriptor client[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 set if(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 client memcpy(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]; } }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值