linux网络编程(epoll反应堆)

来源:互联网 发布:尚学堂大数据极限班 编辑:程序博客网 时间:2024/06/05 16:57

一,epoll反应堆

结构
这里写图片描述

二,epoll编程

/*************************************************************************    > File Name: server_epoll_btree.c    > Author: songli    > QQ: 2734030745    > Mail: 15850774503@163.com    > CSDN: http://my.csdn.net/Poisx    > github: https://github.com/chensongpoixs    > Created Time: Thu 02 Nov 2017 09:43:30 PM CST ************************************************************************/#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <fcntl.h>#include <sys/epoll.h>#include <sys/stat.h>#include <sys/types.h>#include <sys/socket.h>#include <arpa/inet.h>#define SERV_PROT 8888typedef struct xxevent {    int fd; // 描述符    int events;  //事件    void (*call_back)(int fd, int events, void *arg); //call    void *arg;    char buf[FD_SETSIZE];    int buflen;    int fped;}xevent;//btree 树根int fepol = 0;xevent myevents[FD_SETSIZE]; //读取数据void readData(int fd, int events, void *arg);//添加事件void eventadd(int fd, int events, void (*call_back)(int, int, void *), void *arg, xevent *ev) {    printf("方法名:%s \n", __FUNCTION__);    ev->fd = fd;    ev->events = events;    ev->arg = arg;    ev->call_back = call_back;    //添加事件    struct epoll_event epv;    epv.data.ptr = ev;    epv.events = events;        epoll_ctl(fepol, EPOLL_CTL_ADD, fd, &epv); //添加到红黑树上}//设置事件的操作void eventset(int fd, int events, void (*call_back)(int, int, void*), void *arg, xevent *ev) {    printf("方法名:%s\n", __FUNCTION__);    ev->fd = fd;    ev->events = events;    ev->arg = arg;    ev->call_back = call_back;    struct epoll_event epv;    epv.data.ptr = ev;    epv.events = events;    //修改节点事件    epoll_ctl(fepol, EPOLL_CTL_MOD, fd, &epv);}//发送信息void sendData(int fd, int events, void *arg) {    printf("方法名:%s\n", __FUNCTION__);    xevent *ev = arg;    write(fd, ev->buf, ev->buflen);    //修改事件    eventset(fd, EPOLLIN, readData, arg, ev);}//删除节点void eventdel(xevent *ev, int fd, int events) {    printf("方法名:%s\n", __FUNCTION__);    ev->fd = 0;    ev->events = 0;    memset(ev->buf, 0x00, sizeof(ev->buf));    ev->buflen = 0;    ev->arg = NULL;    struct epoll_event epv;    epv.data.ptr = NULL; //指针    epv.events = events; //事件    //删除节点    epoll_ctl(fepol, EPOLL_CTL_DEL, fd, &epv);}//读取数据void readData(int fd, int events, void *arg) {    printf("方法名:%s\n", __FUNCTION__);    xevent *ev = arg;    ev->buflen = read(fd, ev->buf, sizeof(ev->buf));    if (ev->buflen > 0)  { //client发送信息        //添加事件发送信息        eventset(fd, EPOLLOUT, sendData, arg, ev);    } else if (ev->buflen == 0) {        printf("client 退出\n");        close(fd);        //删除节点        eventdel(ev, fd, events);    }else {        perror("read error");        close(fd);        //删除节点        eventdel(ev, fd, events);    }}//新的client链接void initAccept(int fd, int events, void *arg) {    printf("方法名:%s\n", __FUNCTION__);    //   client 的信息的初始化操作    struct sockaddr_in cliaddr;    char strip[16];    socklen_t len = sizeof(cliaddr);    int i;    int connfd = accept(fd, (struct sockaddr *)&cliaddr, &len);    if (connfd > 0) {        printf("client ip:%s,port:%d\n", inet_ntop(AF_INET, &cliaddr.sin_addr.s_addr, strip, sizeof(strip)), htons(cliaddr.sin_port));        for (i = 0; i < FD_SETSIZE; i++ ) {            //判断是否有空位            if (myevents[i].fd == 0)                 break;         }    }    //添加事件操作     client de 信息    eventadd(connfd, EPOLLIN, readData, &myevents[i], &myevents[i]);}int main(int argc, char *argv[]){    int listenfd;    struct sockaddr_in servaddr;    int optval = 1;    //创建socket    listenfd = socket(AF_INET, SOCK_STREAM, 0);    //绑定ip和port    bzero(&servaddr, sizeof(servaddr));    servaddr.sin_family = AF_INET;    servaddr.sin_port = htons(SERV_PROT);    servaddr.sin_addr.s_addr = htonl(INADDR_ANY);    //端口复用    setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(servaddr));    if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)  {        perror("bind error");        return -1;    }    //监听listen    listen(listenfd, 128);    //+++++++++++++        epoll init 操作           ++++++++++++++++===    fepol = epoll_create(FD_SETSIZE); //创建btree     struct epoll_event events[FD_SETSIZE];    //添加事件    eventadd(listenfd, EPOLLIN, initAccept, &myevents[FD_SETSIZE -1], &myevents[FD_SETSIZE - 1]);    while (1) {        //阻塞事件        int  ret = epoll_wait(fepol, events, FD_SETSIZE, -1);        if (ret > 0) {            int i;            for (i = 0; i < ret; i++ ) {                xevent *ev = events[i].data.ptr;                //判断是否有事件                if (ev->events & events[i].events) {                    ev->call_back(ev->fd, ev->events, ev);                }            }        }    }    return 0;}

这里写图片描述