epoll用發

epollserver.cppios

#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 <stdlib.h>
#include <errno.h>
#include <string .h>
#include <iostream>

using namespace  std;

void work(char *str){

    char* p = str;
    while(*p){
        if(*p >= 'a' && *p <= 'z'){
            *p = *p -'a'+'A';
        }
        p++;
    }
}


int main(int argc, char* argv[]){
    int i , listenfd ,connfd ,sockfd , epfd , nfds;
    ssize_t n ;
    char line[1024];
    socklen_t clilen;
    struct sockaddr_in clientaddr ;
    struct sockaddr_in  severaddr ;
    int ret=0 ;

    //申明epoll_event結構體的變量
    //ev用於註冊事件
    //events 數組用於回傳要處理的事件
    struct epoll_event ev;
    struct epoll_event events[20];

    //該函數生成一個epoll專用的文件描述符
    //其中的參數是指定生成文件描述符的最大範圍

// epfd = epoll_create(256);
    epfd = epoll_create1(EPOLL_CLOEXEC);

    //建立套接字 
    listenfd = socket(AF_INET , SOCK_STREAM , 0);

    //設置與要處理的事件相關的文件描述符
    ev.date.fd = listenfd ;

    //設置要處理的事件類型
    //EPOLLIN : 表示對應的文件描述符能夠讀
    //EPOLLOUT :表示對應的文件描述符能夠寫
    //EPOLLERR :發生錯誤

    ev.events = EPOLLIN;

    //註冊epoll事件 
    //EPOLL_CTL_ADD 註冊
    //EPOLL_CTL_MOD 修改
    //EPOLL_CTL_DEL 刪除

    epoll_ctl(epfd , EPOLL_CTL_ADD , listenfd , &ev);

    //設置服務器地址

    bzero(&sereveraddr , sizeof(struct serveraddr));
    serveraddr.sin_family = AF_INET ;
    serveraddr.sin_addr.s_addr = INADDR_ANY;
    serveraddr.sin_port = htons (8000);

    ret = bind (listenfd , (struct scokaddr*)&serveraddr ,
                            sizeof(struct serveraddr));
    if(ret  < 0){

        continue ;
    }
    listen (listenfd , 20);
    while(1){
        //監聽epoll事件的發生
        //超時時間爲500ms 最多能處理20個事件 
        //events 用於保存索監聽到的事件
        //返回監聽到的事件總數

        nfds = epoll_wait(epfd , events , 20 ,500);

        //分別處理各事件 
        for(i =0; i<nfd ; ++i){
            //有客戶端的連接(connect )服務器

            if(events[i].data.fd == listenfd){
            connfd = accept(listenfd , 
                            (struct sockaddr*)&clientaddr ,
                            &clilent);
            if(connfd < 0){
                perror("accept");
                continue ;
            }   
            char *str = inet_ntoa(clientaddr.sin_addr);
            cout << "accept a connect from "<< str << endl;

            //設置用於讀操做的文件描述符

            ev.data.fd = connfd;

            //設置讀註冊
            ev.events = EPOLLIN;

            //註冊

            epoll_ctl(epfd , EPOLL_CTL_ADD , connfd , &ev);

            else if(events[i].events & EPOLLIN){
                cout << "can read data "<< endl;
                sockfd = events[i].data.fd;

                if(sockfd < 0){
                    continue ;
                }

            n = read (sockfd , line ,sizeof(line));
            if(n < 0){
                close(sockfd);
                event[i].data.fd = -1;
                cout << "client closed "<< endl;
                continue;
            }
            cout << "server readline "<< line << endl;

            //處理業務
            work (line);

            //設置用於寫操做的文件描述符

            ev.data.fd = sockfd ; 

            ev.events = EPOLLOUT ;

            //修改sockfd 上要處理的事件爲EPOLLOUT 
            //在接收到客戶端連接時,已經把客服端套接字註冊到epoll
            //因此,此時只須要修改所註冊的事件
            //
            epoll_ctl(epfd , EPOLL_CTL_MOD ,sockfd , &ev);

            }   

            else if(events[i].events & EPOLLOUT ){
                cout << "can read data "<< endl;

                sockfd  = events[i].data.fd;
                write(sockfd , line ,n );

                cout << "server had send data"<< endl;

                ev.data.fd = sockfd ;

                ev.events = EPOLLIN ;

                epoll_ctl(epf , EPOLL_CTL_MOD , sockfd , &ev);

            }
            }   

        }
    }
    return 0;   
}
相關文章
相關標籤/搜索