• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            洗塵齋

            三懸明鏡垂鴻韻,九撩清泉洗塵心

            常用鏈接

            統(tǒng)計(jì)

            最新評(píng)論

            epoll實(shí)現(xiàn)的net_echo程序


            這是我前兩天所做的一個(gè)小練習(xí),用epoll寫(xiě)個(gè)echo程序,里面用共享內(nèi)存存儲(chǔ)訪問(wèn)信息,貼在這里,哪天生疏了還可以過(guò)來(lái)查查~~  更多內(nèi)容請(qǐng)?jiān)L問(wèn): http://lmlf001.blog.sohu.com/



            //net_echo.cpp
            //寫(xiě)一個(gè)程序,支持同時(shí)打開(kāi)10w個(gè)文件句柄,申請(qǐng)1G共享內(nèi)存,是一個(gè)tcp echo的server,采用select或epoll管理多連接
            #include<sys/socket.h>
            #include
            <sys/resource.h>
            #include
            <stdio.h>
            #include
            <sys/epoll.h>
            #include
            <arpa/inet.h>
            #include
            <strings.h>
            #include
            <unistd.h>
            #include
            <fcntl.h>
            #include
            <errno.h>
            #include
            <sys/shm.h>
            #include
            <string.h>
            #include
            <time.h>

            #define SHM_MAX 1000000000UL  //共享內(nèi)存大小
            #define SHM_KEY 7896   //共享內(nèi)存申請(qǐng)時(shí)的key
            #define SERV_PORT 4466   //服務(wù)端口號(hào)
            #define MAX_RLIMIT 100000  //最大訪問(wèn)量
            #define LISTENQ  5    //監(jiān)聽(tīng)隊(duì)列長(zhǎng)度
            #define MAX_LINE 128   //緩存長(zhǎng)度
            const char *local_addr="127.0.0.1";//綁定服務(wù)地址

            struct access_info{  //記錄客戶(hù)訪問(wèn)信息
             time_t a_time;  //客戶(hù)訪問(wèn)時(shí)間
             in_addr_t a_ip;  //客戶(hù)ip
             int a_errno;  //是否訪問(wèn)成功,成功為0,否則為其錯(cuò)誤號(hào)
            };

            bool setnonblocking(int fd); //設(shè)置fd為非阻塞模式
            bool set_fd_limit(unsigned int max); //設(shè)置系統(tǒng)允許的進(jìn)程所能打開(kāi)的文件描述符的最大值

            int main(int argc,char **argv)
            {
                
            int listenfd=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);//建立serv socket
                if(listenfd<0){
                    perror(
            "create socket failed!");
                    
            return -1;
                }

                
            struct sockaddr_in servaddr,clientaddr;
                bzero(
            &servaddr,sizeof(servaddr));
                servaddr.sin_family
            =AF_INET;
                servaddr.sin_port
            =htons(SERV_PORT);
                inet_aton(local_addr,
            &(servaddr.sin_addr));
                
            if(bind(listenfd,(sockaddr *)&servaddr,sizeof(servaddr))<0)  //綁定本機(jī)地址
                {
                    perror(
            "bind error!");
                    
            return -1;
                }

             
             
            if(!set_fd_limit(MAX_RLIMIT)){
              perror(
            "setrlimit failed!");
              
            return -1;
             }
                   
             
            struct epoll_event ev,events[20];
             
            int epfd=epoll_create(MAX_RLIMIT);  //epoll_create
             if(!setnonblocking(listenfd))return -1;
             ev.data.fd
            =listenfd;
             ev.events
            =EPOLLIN|EPOLLET;
             epoll_ctl(epfd,EPOLL_CTL_ADD,listenfd,
            &ev);//把listenfd加入到epoll監(jiān)聽(tīng)隊(duì)列
             
             
            int shm_id=shmget(SHM_KEY,SHM_MAX,IPC_CREAT|0600); //申請(qǐng)共享內(nèi)存
             if(shm_id==-1){
              perror(
            "shmget");
              
            return -2;
             }
             
            struct access_info  client_info,*pos;  //客戶(hù)信息
             int *head;
             head
            =(int *)shmat(shm_id,0,0);
             
            if(int(head)==-1){
              perror(
            "shmat");
              
            return -1;
             }
             
            *head=1;      //服務(wù)器在運(yùn)行狀態(tài),若該值變?yōu)?,則關(guān)閉服務(wù)器
             if(*(head+1)!=1){    // head+1服務(wù)器是否第一次運(yùn)行,head+2共享內(nèi)存存儲(chǔ)的信息數(shù)量 
              *(head+1)=1;             //  ___________  
              *(head+2)=0;   //head-->|___ 0/1___|  服務(wù)器的運(yùn)行狀態(tài) 
             }                            //   |___ 0/1___|  共享內(nèi)存是否使用過(guò),是為1,否則為0
                                           
            //   |___  n____|   共享內(nèi)存存儲(chǔ)信息數(shù)量  0~SHM_MAX/(3*4*8)-1
             pos=(struct access_info *)(head)+1+*(head+2); //記錄信息的開(kāi)始位置
             
             listen(listenfd,LISTENQ);  
            //監(jiān)聽(tīng)客戶(hù)端請(qǐng)求
             int nfds,i,connfd,sockfd,n;
             socklen_t len;
             
            char line[MAX_LINE];
             
            while(*head)
             {
              nfds
            =epoll_wait(epfd,events,20,500); //檢測(cè)活躍連接
              for(i=0;i<nfds;i++)
              {
               
            if(events[i].data.fd==listenfd)    //有新連接到來(lái)
               {
                len
            =sizeof(clientaddr);
                connfd
            =accept(listenfd,(sockaddr *)&clientaddr,&len);
                
                client_info.a_time
            =time(NULL);     //注冊(cè)客戶(hù)信息
                client_info.a_ip=clientaddr.sin_addr.s_addr;
                client_info.a_errno
            =0;
                
                
            if(connfd<0){
                 perror(
            "connfd<0!");
                 client_info.a_errno
            =errno;
                 
            continue;
                }
                
                memcpy(pos,
            &client_info,sizeof(client_info));
                pos
            ++;         //共享內(nèi)存指針后移,并把信息數(shù)量加1
                if((*(head+2))++>4*SHM_MAX/(3*8*4*5))  //共享內(nèi)存剩余不足1/5時(shí)發(fā)出警告信息
                 fprintf(stderr,"Warning:share memory is being not enough\n Left:%d\n",SHM_MAX-*(head+2)*3*4*8);
                 
                
                
            if(!setnonblocking(connfd))continue;
                ev.data.fd
            =connfd;
                ev.events
            =EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_ADD,connfd,
            &ev);//新連接加入epoll_wait
               }
               
            else if(events[i].events&EPOLLIN)   //連接可讀
               {
                
            if((sockfd=events[i].data.fd)<0)continue;
                
            while((n=read(sockfd,line,MAX_LINE))==MAX_LINE)
                 write(sockfd,line,n);
                
            if(n<0)
                {
                 
            if (errno == ECONNRESET) {
                  events[i].data.fd 
            = -1;
                  epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);
                  close(sockfd);
                  
            continue;
                 }
                 
            else continue;  //恰好讀完MAX_LINE后無(wú)數(shù)據(jù)
                }
                
            else if(n==0){      //客戶(hù)端關(guān)閉連接
                 epoll_ctl(epfd,EPOLL_CTL_DEL,sockfd,NULL);
                 close(sockfd);
                 events[i].data.fd 
            = -1;
                 
            continue;
                }
                
            else write(sockfd,line,n);
               }
            /*   else if(events[i].events&EPOLLOUT)
               {
                sockfd=events[i].data.fd;
                if(sockfd<0)continue;
                write(sockfd,line,n);
                ev.data.fd=sockfd;
                ev.events=EPOLLIN|EPOLLET;
                epoll_ctl(epfd,EPOLL_CTL_MOD,sockfd,&ev);
               }
             
            */ }
                }
             shmdt(head);  
            //卸載共享內(nèi)存
             close(epfd);
             close(listenfd);
             
            return 0;
            }

            bool setnonblocking(int sock)
            {
                
            int opts;
                opts
            =fcntl(sock,F_GETFL);
                
            if(opts<0)
             {
              perror(
            "fcntl(sock,GETFL)");
              
            return false;
                }
             opts 
            = opts|O_NONBLOCK;
             
            if(fcntl(sock,F_SETFL,opts)<0)
             {
              perror(
            "fcntl(sock,SETFL,opts)");
              
            return false;
                }
             
            return true;
            }

            bool set_fd_limit(unsigned int max)
            {
                
            struct rlimit rlim,rlim_new;
                
            if (getrlimit(RLIMIT_NOFILE, &rlim)!=0)
                    
            return false;
                
            if(rlim.rlim_cur>=max) return true;

                
            if(rlim.rlim_max==RLIM_INFINITY||rlim.rlim_max>=max){
                    rlim_new.rlim_max 
            = rlim.rlim_max;
                    rlim_new.rlim_cur 
            = max;
                }
                
            else{
                    
            if(geteuid()!=0){errno=1;return false; }
              rlim_new.rlim_max
            =rlim_new.rlim_cur=max;
                }
             
            if (setrlimit(RLIMIT_NOFILE, &rlim_new)!=0) {/* failed. try raising just to the old max */
              
            int err=errno;
              setrlimit(RLIMIT_NOFILE, 
            &rlim);
              errno
            =err;
              
            return false;
                }
             
            return true;
            }

            /*----------------------------------------------------------------*/         

                             

             

            //net_echo_shutdown.cpp
            //啟動(dòng)該進(jìn)程時(shí),關(guān)閉net_echo服務(wù)進(jìn)程

            #include
            <sys/shm.h>
            #include
            <stdio.h>
            #include
            <unistd.h>
            #include
            <errno.h>
            #define SHM_MAX 1000000000UL  //共享內(nèi)存大小
            #define SHM_KEY 7896   //共享內(nèi)存申請(qǐng)時(shí)的key

            #ifndef IPC_ALLOC
            #define IPC_ALLOC IPC_CREAT
            #endif


            int main(int argc,char **argv)
            {
             
            if(geteuid()!=0){
              errno
            =1;
              perror(
            "net_echo_shutdown:");
              
            return -1;
             }
             
            int shmid;
             
            if((shmid=shmget(SHM_KEY,SHM_MAX,IPC_ALLOC|0600))==-1)
             {
              perror(
            "shmget()");
              
            return -1;
             }
             
            int *head=(int *)shmat(shmid,0,0);
             
            if(int(head)==-1){
              perror(
            "shmat()");
              
            return -1;
             }
             
            if(*head!=1){     //服務(wù)器并未運(yùn)行
              fprintf(stderr,"Net_echo server is not running\n");
              
            return -1;
             }
             
            *head=0;   //設(shè)置關(guān)閉標(biāo)志
             printf("Shutdown the echo server\n");
             sleep(
            2);
             shmdt(head);
             
            return 0;
            }

             /******************************************************************/

            //print_shm.cpp
            //讀取并打印共享內(nèi)存信息
            #include<stdio.h>
            #include
            <sys/shm.h>
            #include
            <unistd.h>
            #include
            <errno.h>
            #include
            <time.h>
            #include
            <sys/socket.h>
            #include
            <arpa/inet.h>
            #include
            <string.h>
            #define SHM_KEY 7896
            #define SHM_MAX 1000000000UL
            #ifndef IPC_ALLOC
            #define IPC_ALLOC IPC_CREAT
            #endif

            struct access_info{  //記錄客戶(hù)訪問(wèn)信息
             time_t a_time;  //客戶(hù)訪問(wèn)時(shí)間
             in_addr_t a_ip;  //客戶(hù)ip
             int a_errno;  //是否訪問(wèn)成功,成功為0,否則為其錯(cuò)誤號(hào)
            };

            int main(int argc,char **argv)
            {
             
            if(geteuid()!=0){
              errno
            =1;
              perror(
            "print_shm:");
              
            return -1;
             }
             
            int shmid=shmget(SHM_KEY,SHM_MAX,IPC_ALLOC|0600);
             
            if(shmid==-1)
             {
              perror(
            "shmget()");
              
            return -1;
             }
             
            int *head=(int *)shmat(shmid,0,0);
             
            if(int(head)==-1){
              perror(
            "shmat()");
              
            return -1;
             }
             
            if(*(head+1)!=1){
              fprintf(stderr,
            "SHM have not be used!\n");
              
            return -1;
             }
             
            struct access_info *pos=(access_info *)(head)+1;
             
            for(int i=0;i<*(head+2);i++,pos++)
              printf(
            "%-15s%-10s%20s%s",inet_ntoa(*(in_addr *)&(pos->a_ip)),pos->a_errno==0?"Success!":"Failed:",
               pos
            ->a_errno==0?"":strerror(pos->a_errno),ctime(&pos->a_time));
             
             shmdt(head);
             
            return 0;
            }

            posted on 2007-09-08 20:49 芥之舟 閱讀(1960) 評(píng)論(0)  編輯 收藏 引用 所屬分類(lèi): socket網(wǎng)絡(luò)編程

            久久亚洲中文字幕精品有坂深雪| 久久精品免费一区二区三区| 久久伊人精品一区二区三区| 亚洲午夜久久久久妓女影院 | 久久本道久久综合伊人| 午夜精品久久久久久久无码| 77777亚洲午夜久久多人| 97久久精品国产精品青草| 久久夜色精品国产| 久久人人爽人人爽人人AV东京热| 99久久精品费精品国产| 中文字幕人妻色偷偷久久| 精品综合久久久久久88小说| 无码伊人66久久大杳蕉网站谷歌| 久久最新精品国产| 久久精品国产亚洲av麻豆色欲| 久久精品国产一区二区电影| 久久狠狠高潮亚洲精品| 久久99热这里只频精品6| 嫩草影院久久99| 丰满少妇人妻久久久久久| 亚洲а∨天堂久久精品9966| 国产视频久久| 久久精品中文字幕久久| 久久国产亚洲精品无码| 亚洲va久久久久| 久久久黄色大片| 久久久久亚洲av毛片大| 久久99精品久久久久久噜噜| 国产一区二区三区久久| 久久中文骚妇内射| 久久亚洲AV成人出白浆无码国产| 午夜精品久久久久| 国内精品伊人久久久久妇| 中文成人无码精品久久久不卡| 久久强奷乱码老熟女| 久久亚洲国产精品五月天婷| 久久久久无码精品| 久久精品国产亚洲AV久| 久久精品国产亚洲αv忘忧草 | 久久精品国产欧美日韩99热|