• <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>

            洗塵齋

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

            常用鏈接

            統計

            最新評論

            epoll實現的net_echo程序


            這是我前兩天所做的一個小練習,用epoll寫個echo程序,里面用共享內存存儲訪問信息,貼在這里,哪天生疏了還可以過來查查~~  更多內容請訪問: http://lmlf001.blog.sohu.com/



            //net_echo.cpp
            //寫一個程序,支持同時打開10w個文件句柄,申請1G共享內存,是一個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  //共享內存大小
            #define SHM_KEY 7896   //共享內存申請時的key
            #define SERV_PORT 4466   //服務端口號
            #define MAX_RLIMIT 100000  //最大訪問量
            #define LISTENQ  5    //監聽隊列長度
            #define MAX_LINE 128   //緩存長度
            const char *local_addr="127.0.0.1";//綁定服務地址

            struct access_info{  //記錄客戶訪問信息
             time_t a_time;  //客戶訪問時間
             in_addr_t a_ip;  //客戶ip
             int a_errno;  //是否訪問成功,成功為0,否則為其錯誤號
            };

            bool setnonblocking(int fd); //設置fd為非阻塞模式
            bool set_fd_limit(unsigned int max); //設置系統允許的進程所能打開的文件描述符的最大值

            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)  //綁定本機地址
                {
                    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監聽隊列
             
             
            int shm_id=shmget(SHM_KEY,SHM_MAX,IPC_CREAT|0600); //申請共享內存
             if(shm_id==-1){
              perror(
            "shmget");
              
            return -2;
             }
             
            struct access_info  client_info,*pos;  //客戶信息
             int *head;
             head
            =(int *)shmat(shm_id,0,0);
             
            if(int(head)==-1){
              perror(
            "shmat");
              
            return -1;
             }
             
            *head=1;      //服務器在運行狀態,若該值變為0,則關閉服務器
             if(*(head+1)!=1){    // head+1服務器是否第一次運行,head+2共享內存存儲的信息數量 
              *(head+1)=1;             //  ___________  
              *(head+2)=0;   //head-->|___ 0/1___|  服務器的運行狀態 
             }                            //   |___ 0/1___|  共享內存是否使用過,是為1,否則為0
                                           
            //   |___  n____|   共享內存存儲信息數量  0~SHM_MAX/(3*4*8)-1
             pos=(struct access_info *)(head)+1+*(head+2); //記錄信息的開始位置
             
             listen(listenfd,LISTENQ);  
            //監聽客戶端請求
             int nfds,i,connfd,sockfd,n;
             socklen_t len;
             
            char line[MAX_LINE];
             
            while(*head)
             {
              nfds
            =epoll_wait(epfd,events,20,500); //檢測活躍連接
              for(i=0;i<nfds;i++)
              {
               
            if(events[i].data.fd==listenfd)    //有新連接到來
               {
                len
            =sizeof(clientaddr);
                connfd
            =accept(listenfd,(sockaddr *)&clientaddr,&len);
                
                client_info.a_time
            =time(NULL);     //注冊客戶信息
                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
            ++;         //共享內存指針后移,并把信息數量加1
                if((*(head+2))++>4*SHM_MAX/(3*8*4*5))  //共享內存剩余不足1/5時發出警告信息
                 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后無數據
                }
                
            else if(n==0){      //客戶端關閉連接
                 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);  
            //卸載共享內存
             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
            //啟動該進程時,關閉net_echo服務進程

            #include
            <sys/shm.h>
            #include
            <stdio.h>
            #include
            <unistd.h>
            #include
            <errno.h>
            #define SHM_MAX 1000000000UL  //共享內存大小
            #define SHM_KEY 7896   //共享內存申請時的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){     //服務器并未運行
              fprintf(stderr,"Net_echo server is not running\n");
              
            return -1;
             }
             
            *head=0;   //設置關閉標志
             printf("Shutdown the echo server\n");
             sleep(
            2);
             shmdt(head);
             
            return 0;
            }

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

            //print_shm.cpp
            //讀取并打印共享內存信息
            #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{  //記錄客戶訪問信息
             time_t a_time;  //客戶訪問時間
             in_addr_t a_ip;  //客戶ip
             int a_errno;  //是否訪問成功,成功為0,否則為其錯誤號
            };

            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 芥之舟 閱讀(1954) 評論(0)  編輯 收藏 引用 所屬分類: socket網絡編程

            AAA级久久久精品无码区| 久久久免费精品re6| 国产成人精品久久综合 | 久久涩综合| 中文字幕乱码久久午夜| 99久久精品国内| 亚洲精品NV久久久久久久久久| 无码日韩人妻精品久久蜜桃| 国产午夜电影久久| 久久九九兔免费精品6| 色综合合久久天天综合绕视看| 欧美一级久久久久久久大片| 99久久99久久精品免费看蜜桃| 久久性精品| 成人国内精品久久久久影院| 伊人色综合久久天天人守人婷| 国产精品久久国产精品99盘| 久久久国产视频| 久久久精品日本一区二区三区| 国内精品久久久久影院优| 久久丝袜精品中文字幕| 好属妞这里只有精品久久| 久久久久亚洲av综合波多野结衣| 久久777国产线看观看精品| 一本色道久久88精品综合| 香蕉久久夜色精品国产尤物| 国产精品成人精品久久久| 国产精品久久毛片完整版| 麻豆成人久久精品二区三区免费| 一个色综合久久| 久久亚洲国产成人影院| 亚洲精品国产自在久久| 色偷偷88欧美精品久久久| 久久精品综合一区二区三区| 久久亚洲精品视频| 91亚洲国产成人久久精品网址| 久久精品国产99国产电影网| 久久精品国产半推半就| 青青草原综合久久大伊人精品| 久久电影网一区| 成人a毛片久久免费播放|