Linux 网络编程(epoll)

  • 服务器端代码
#include<stdio.h>  
#include<stdlib.h>  
#include<string.h>  
#include<sys/socket.h>  
#include<sys/types.h>  
#include<unistd.h>  
#include<netinet/in.h>
#include <errno.h>
#include <sys/epoll.h>

int main(int argc, char** argv){

    int old_fd,new_fd;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;

    char recvbuf[1024];
    int port = 8001;
    int len,nbytes,epfd,i;
    //声明epoll_event结构体的变量,ev用于注册事件,数组用于回传要处理的事件
    struct epoll_event ev,events[20];

    //生成用于处理accept的epoll专用的文件描述符,参数为最大的监听数目
    epfd = epoll_create(100);

    if((old_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == 0){
        fprintf(stderr, "socket Error:%s
a", strerror(errno));   
        exit(1);
    }

    bzero(&server_addr, sizeof(struct sockaddr_in));
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr =  htonl(INADDR_ANY);

    if((bind(old_fd, &server_addr, sizeof(server_addr))) == -1){
        fprintf(stderr, "bind Error:%s
a", strerror(errno));   
        exit(1);
    }

    if(listen(old_fd, 10) == -1){
        fprintf(stderr, "listen Error:%s
a", strerror(errno));   
        exit(1);
    }

    ev.data.fd = old_fd;
    //设置要处理的事件类型
    ev.events = EPOLLIN;
    //EPOLL_CTL_ADD 注册新的fd
    //EPOLL_CTL_MOD 修改已注册的fd
    //EPOLL_CTL_DEL 删除epfd中的一个fd
    epoll_ctl(epfd, EPOLL_CTL_ADD, old_fd, &ev); 

    while(1){
        //int epoll_wait(int epfd, struct epoll_event * events, intmaxevents, int timeout);
        //maxevents:每次能处理的事件数;
        //timeout:等待I/O事件发生的超时值;-1相当于阻塞,0相当于非阻塞。一般用-1即可
        len = epoll_wait(epfd,events,20,500);

        for(i = 0; i < len; i++){
            if(events[i].data.fd == old_fd){
                if ((new_fd = accept(old_fd, 
                    (struct sockaddr *)&client_addr, 
                    &len)) == -1) {   
                            fprintf(stderr, "Accept error:%s
a", strerror(errno));   
                        exit(1);   
                }

                ev.data.fd=new_fd;

              /*EPOLLIN:        表示对应的文件描述符上有可读数据
                 EPOLLOUT:         表示可以写数据;
                EPOLLPRI:         表示对应的文件描述符有紧急的数据可读
                EPOLLERR:         表示对应的文件描述符发生错误;
                 EPOLLHUP:         表示对应的文件描述符被挂断;
                EPOLLET:          将EPOLL设为边缘触发ET模式
                                   ET模式:Edge Triggered epoll_wait 只有在读写状态改变时才返回
                                   LT模式:LevelTriggered (默认) epoll_wait 会一致有
                EPOLLONESHOT:     只监听一次事件                                    */
                ev.events=EPOLLIN;//对接入的新套接字注册epoll时间监听
                epoll_ctl(epfd, EPOLL_CTL_ADD, new_fd, &ev);
            }else if(events[i].events&EPOLLIN){
                if (events[i].data.fd < 0) 
                    continue;

                nbytes = recv(events[i].data.fd, recvbuf, sizeof(recvbuf), 0);
                recvbuf[nbytes] = '';

                printf("recv data is:%s
",recvbuf);
            }
        }
    }

    exit(0);
}
原文地址:https://www.cnblogs.com/Fredric-2013/p/4549321.html