服务器端: /* * main.cpp * * Created on: 2010-3-22 * Author: wlOf */ #include <iostream> #include <sys/socket.h> #include <sys/epoll.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <strings.h> #include <errno.h> #include <string.h> #include <sys/mman.h> #include <sys/types.h> #include <string.h> #include <signal.h> #include <time.h> using namespace std; #define SERV_PORT 5555 #define LISTENQ 1000 #define SOCKET_ERROR -1 #define PERPNUM 1000 void setnonblocking(int sock) { int opts; opts=fcntl(sock,F_GETFL); if(opts<0) { perror("fcntl(sock,GETFL)"); exit(1); } opts = opts|O_NONBLOCK; if(fcntl(sock,F_SETFL,opts)<0) { perror("fcntl(sock,SETFL,opts)"); exit(1); } } typedef struct tagGateSocket { int sockfd; char *nAddr; int nPort; bool isAvailable; time_t begin; struct epoll_event ev; }GS_SOCKET, *PGS_SOCKET; socklen_t clilen; struct epoll_event ev; struct epoll_event *gxev=(struct epoll_event *)mmap(NULL,sizeof(struct epoll_event)*PERPNUM,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); int *epfd=(int *)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); int *i=(int *)mmap(NULL,sizeof(int),PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); PGS_SOCKET gx=(PGS_SOCKET)mmap(NULL,sizeof(GS_SOCKET)*10000,PROT_READ|PROT_WRITE,MAP_SHARED|MAP_ANONYMOUS,-1,0); void timersc(int sig) { if(sig == SIGALRM) { for(int i=0;i<10000;++i) { if((gx+i)->isAvailable==1) cout<<(gx+i)->nAddr<<"is connected!"<<endl; } } } void sc() { while(1) { signal(SIGALRM, timersc); alarm(1); sleep(1); } } //void timergb(int sig) //{ // if(sig == SIGALRM){ // for(int i=0;i<10000;++i) // { // if((time(NULL)-(gx+i)->begin)>15) // {(gx+i)->isAvailable=0;close((gx+i)->sockfd);} // } // } //} //void gb() //{ // while(1){ // signal(SIGALRM, timergb); // alarm(15); // sleep(15); // } //} int main() { int listenfd, connfd, sockfd,nfds,bytes,j=0,pidz[10]={0},scp=0/*,gbp=0*/,acp=0; PGS_SOCKET tt=gx; char buf[10]=""; for(*i=0;*i<10000;*i++) (tt+*i)->isAvailable=0; //生成用于处理accept的epoll专用的文件描述符 *epfd=epoll_create(10000); struct sockaddr_in clientaddr; struct sockaddr_in serveraddr; if((listenfd = socket(AF_INET, SOCK_STREAM, 0))==-1) { perror("listenfd创建出错!"); exit(1); } //把socket设置为非阻塞方式 setnonblocking(listenfd); //设置与要处理的事件相关的文件描述符 //ev.data.fd=listenfd; //设置要处理的事件类型 //ev.events=EPOLLIN|EPOLLET; //注册epoll事件 //epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,&ev); bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_addr.s_addr = INADDR_ANY; serveraddr.sin_port=htons(SERV_PORT); if(bind(listenfd,(struct sockaddr *)&serveraddr, sizeof(struct sockaddr))==-1) { perror("bind出错!"); exit(1); } if(listen(listenfd, LISTENQ)==-1) { perror("listen出错!"); exit(1); } if(scp==0) { scp=fork(); if(scp==0)sc(); } if(acp==0){ acp=fork(); if(acp!=0){ while(1) { sleep(1); connfd = accept(listenfd,(sockaddr *)&clientaddr,&clilen); if(connfd==-1) { perror("accept出错!"); continue; } setnonblocking(connfd); char *str = inet_ntoa(clientaddr.sin_addr); cout<<"connect from >>"<<str<<endl; while(tt->isAvailable!=0)tt++; tt->isAvailable=1; tt->nAddr=str; tt->sockfd=connfd; tt->ev.data.fd = connfd; tt->ev.events=EPOLLIN|EPOLLET; tt->begin=time(NULL); epoll_ctl(*epfd,EPOLL_CTL_ADD,tt->sockfd,&(tt->ev)); tt=gx; } } else { for ( ; ; ) { //等待epoll事件的发生 nfds=epoll_wait(*epfd,gxev,PERPNUM,1000); // if(gbp==0){ // gbp=fork(); // if(gbp==0)gb(); // } //处理所发生的所有事件 for(*i=0;*i<nfds;*i++) { re: // if((gxev+i)->data.fd==listenfd) // { // connfd = accept(listenfd,(sockaddr *)&clientaddr,&clilen); // if(connfd==-1) // { // perror("accept出错!"); // continue; // } // setnonblocking(connfd); // char *str = inet_ntoa(clientaddr.sin_addr); // cout<<"connect from >>"<<str<<endl; // // while(tt->isAvailable!=0)tt++; // tt->isAvailable=1; // tt->nAddr=str; // tt->sockfd=connfd; // tt->ev.data.fd = connfd; // tt->ev.events=EPOLLIN|EPOLLOUT|EPOLLET; // tt->begin=time(NULL); // // epoll_ctl(*epfd,EPOLL_CTL_ADD,tt->sockfd,&(tt->ev)); // tt=gx; // } //else //{ tt=gx; for(j=0;(tt+j)->sockfd!=(gxev+*i)->data.fd;++j){} if(pidz[j/1000]==0) {//没有这个子进程 pidz[j/1000]=fork(); if(pidz[j/1000]==0) {//子进程 pidz[j/1000]=getpid(); if((gxev+*i)->events&EPOLLIN) { printf("[%d]reading!/n",getpid()); if ((sockfd = (gxev+*i)->data.fd) < 0) continue; if((bytes=recv(sockfd,buf,sizeof(buf),0))==SOCKET_ERROR) { printf("errno:%d bytes:%d recv failed!/n",errno,bytes); continue; } buf[bytes]='/0'; printf("S:Message from %s:%s/n",(tt+j)->nAddr,buf); if(send(sockfd,buf,strlen(buf),0)==SOCKET_ERROR) { printf("send failed!"); goto re; } // //设置用于写操作的文件描述符 // ev.data.fd=sockfd; // //设置用于注测的写操作事件 // ev.events=EPOLLIN|EPOLLOUT|EPOLLET; // //修改sockfd上要处理的事件为EPOLLOUT // epoll_ctl(*epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if((gxev+*i)->events&EPOLLOUT) { cout<<"UFO"<<endl; // sockfd = (gxev+i)->data.fd; // write(sockfd, buf, strlen(buf)); // //设置用于读操作的文件描述符 // ev.data.fd=sockfd; // //设置用于注测的读操作事件 // ev.events=EPOLLIN|EPOLLOUT|EPOLLET; // //修改sockfd上要处理的事件为EPOLIN // epoll_ctl(*epfd,EPOLL_CTL_MOD,sockfd,&ev); } goto re; } } else { if(pidz[j/1000]==getpid()) { if((gxev+*i)->events&EPOLLIN) { printf("[%d]reading!/n",getpid()); if ((sockfd = (gxev+*i)->data.fd) < 0) continue; if((bytes=recv(sockfd,buf,sizeof(buf),0))==SOCKET_ERROR) { printf("errno:%d bytes:%d recv failed!/n",errno,bytes); continue; } buf[bytes]='/0'; printf("S:Message from %s:%s/n",(tt+j)->nAddr,buf); if(send(sockfd,buf,strlen(buf),0)==SOCKET_ERROR) { printf("send failed!"); continue; } //设置用于写操作的文件描述符 ev.data.fd=sockfd; //设置用于注测的写操作事件 ev.events=EPOLLIN|EPOLLOUT|EPOLLET; //修改sockfd上要处理的事件为EPOLLOUT epoll_ctl(*epfd,EPOLL_CTL_MOD,sockfd,&ev); } else if((gxev+*i)->events&EPOLLOUT) { cout<<"UFO"<<endl; // sockfd = (gxev+i)->data.fd; // write(sockfd, buf, strlen(buf)); // //设置用于读操作的文件描述符 // ev.data.fd=sockfd; // //设置用于注测的读操作事件 // ev.events=EPOLLIN|EPOLLOUT|EPOLLET; // //修改sockfd上要处理的事件为EPOLIN // epoll_ctl(*epfd,EPOLL_CTL_MOD,sockfd,&ev); } goto re; } } //} usleep(500); } } } } return 0; } 客户端: /* * main.cpp * * Created on: 2010-3-12 * Author: wlOf */ #include <iostream> #include <sys/socket.h> #include <sys/epoll.h> #include <netinet/in.h> #include <arpa/inet.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <pthread.h> #include <stdlib.h> #include <strings.h> #include <errno.h> #include <string.h> #include <netdb.h> using namespace std; #define SERV_PORT 5555 #define SOCKET_ERROR -1 int main() { int sockfd,bytes,sendn; char *server_addr="127.0.0.1"; struct sockaddr_in serveraddr; if((sockfd = socket(AF_INET, SOCK_STREAM, 0))==-1) { perror("socket创建出错!"); exit(1); } bzero(&serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; serveraddr.sin_port=htons(SERV_PORT); inet_aton(server_addr,&(serveraddr.sin_addr)); if(connect(sockfd,(struct sockaddr *)&serveraddr, sizeof(struct sockaddr))==-1) { perror("connect出错!"); exit(1); } char buf[10]="1234567"; while(1) { if((sendn=send(sockfd,buf,strlen(buf),0))==SOCKET_ERROR) { printf("send failed!"); /*exit(-1)*/continue; } else { cout<<"send "<<sendn<<endl; if((bytes=recv(sockfd,buf,sizeof(buf),0))==SOCKET_ERROR) { printf("errno:%d recv failed!/n",errno); /*exit(-1)*/continue; } else { buf[bytes]='/0'; printf("C:Message from %s:%s/n",inet_ntoa(serveraddr.sin_addr),buf); } } } return 0; }