美文网首页
Linux--epoll反应堆

Linux--epoll反应堆

作者: 锈色的栅栏 | 来源:发表于2024-11-04 09:06 被阅读0次

epoll反应堆的概述

epoll反应堆的核心思想:将文件描述符、事件、回调函数用自定义结构体封装在一起,当某个文件描述符的事件被触发,调用其回调函数即可

示例代码

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>//socket
#include <netinet/in.h> //struct sockaddr_in
#include <strings.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <sys/epoll.h>

int create_tcp_socket(unsigned short port);
void sys_err(const char *err);

typedef void (*CALLBACK)(void *arg);
typedef struct {   
            int epfd;    int fd;//文件描述符
            int event; //存放事件
            CALLBACK callback;
            void *arg;
}MY_EVENT;

void event_add(int epfd,int fd,int event,CALLBACK callback,MY_EVENT *my_ev_p){
        my_ev_p->epfd = epfd;
        my_ev_p->fd = fd;
        my_ev_p->event = event;
        my_ev_p->callback = callback;
        struct epoll_event ev;
        ev.events = event;
        ev.data.ptr = my_ev_p;
        epoll_ctl(epfd,EPOLL_CTL_ADD,fd,&ev);
}

void read_data(void *arg){   
        MY_EVENT *my_ev_p = (MY_EVENT *)arg;   
        unsigned char buf[1500] = "";   
        int n = recv(my_ev_p->fd,buf,sizeof(buf),0);   
        if (n <= 0)
        {
                struct epoll_event ev;
                ev.events = my_ev_p->event;
                ev.data.ptr = NULL;
                epoll_ctl(my_ev_p->epfd,EPOLL_CTL_DEL,my_ev_p->fd,&ev);
                close(my_ev_p->fd);
                if(my_ev_p != NULL){
                        free(my_ev_p);
                        my_ev_p = NULL;
                }
         }else if (n > 0)
        {
                printf("%s\n",buf);
                int res = send(my_ev_p->fd,buf,n,0);
                if(res > 0){
                        printf("send success\n");
                }
         }
}

void initAccept(void *arg){
        MY_EVENT *my_ev_p = (MY_EVENT *)arg;
        struct sockaddr_in cil_addr;
        socklen_t cli_len = sizeof(cil_addr);
        int cfd = accept(my_ev_p->fd,(struct sockaddr *)&cil_addr,&cli_len);
        printf("connect %s : %hu\n",
        inet_ntoa(cil_addr.sin_addr),ntohs(cil_addr.sin_port));
        MY_EVENT *cfd_p = (MY_EVENT *)calloc(1,sizeof(MY_EVENT));
        event_add(my_ev_p->epfd,cfd,EPOLLIN,read_data,cfd_p);
}

int main(int argc,char *argv[]) {
        int lfd = create_tcp_socket(9999);
        int epfd = epoll_create(1);//创建epoll的树   
        MY_EVENT *lfd_p = (MY_EVENT *)calloc(1,sizeof(MY_EVENT));            event_add(epfd,lfd,EPOLLIN,initAccept,lfd_p);
        struct epoll_event evs[1024];
        while(1){       
                int n = epoll_wait(epfd,evs,1024,-1);
                if(n <= 0){
                        sys_err("epoll_wait"); 
                 }else{
                        int i = 0;
                        for ( i = 0; i < n; i++)
                        { 
                               MY_EVENT *p = evs[i].data.ptr;
                                p->callback(p);
                        }
                    }
        }
        close(epfd);
        close(lfd);
        return 0;
}

int create_tcp_socket(unsigned short port){
            int lfd = socket(AF_INET,SOCK_STREAM,0);
            if(lfd < 0)
                    sys_err("socket error");
            int opt = 1;
            setsockopt(lfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
            struct sockaddr_in my_addr;
            bzero(&my_addr,sizeof(my_addr));
            my_addr.sin_family = AF_INET;
            my_addr.sin_port = htons(port);
            my_addr.sin_addr.s_addr = htonl(INADDR_ANY);
            int ret = bind(lfd,(struct sockaddr *)&my_addr,sizeof(my_addr));
            if(ret < 0) 
                   sys_err("bind error");
            listen(lfd,128);
            return lfd;
}

void sys_err(const char *err){
        perror(err);   
        _exit(-1);
}

相关文章

网友评论

      本文标题:Linux--epoll反应堆

      本文链接:https://www.haomeiwen.com/subject/qjnidjtx.html