epoll中epoll_data_t 中fd和ptr的用法

文章是网上内容总结,为了自己下次好找,所以写到自己博客里边了。

fd存放文件描述符,所以我们一般直接

struct epoll_event event;
event.events=EPOLLIN;
 event.data.fd = 0;//监听标准输入

 epoll_data_t中的ptr怎么用呢?是给用户自由使用的。epoll 不关心里面的内容。用户可以用 epoll_data 这个 union 在 epoll_event 里面附带一些自定义的信息,这个 epoll_data 会随着 epoll_wait 返回的 epoll_event 一并返回。那附带的自定义消息,就是ptr指向这个自定义消息。

struct myevent_s {
    int fd;
    int events;
    void *arg;
    void (*call_back)(int fd, int events, void *arg);
    int status;
    char buf[BUFLEN];
    int len;
    long last_active;
};
struct myevent_s g_event; 
struct epoll_event epv = {0, {0}}; 
epv.data.ptr=&g_event;
//然后在epoll_wait()的第二个参数中的data.ptr会原封不动的把上边的g_event返回给我们,所以我们可以利用这个ptr传参。

在epoll模型中使用了一个struct epoll_event的结构体:

typedef union epoll_data {
void *ptr;
int fd;
uint32_t u32;
uint64_t u64;
} epoll_data_t;

struct epoll_event {
uint32_t events; /* Epoll events */
epoll_data_t data; /* User data variable */
};
可以看到,其中的data成员是一个联合体,其成员有一个void*的指针,还有一个fd,一般用法是直接把socket赋给fd即可,但是,有了这个void*的指针,我们就可以在注册socket的时候,传进我们想要的参数。在wait出来的时候,我们可以用我们自己的函数进行处理。代码如下:
server.c是一个简单的回射服务器,用于接收客户端发过来的数据,然后简单回发给客户端。
client.c是一个简单的客户端程序,由命令行参数输入IP和端口8888,由用户从键盘输入数据,直接发给服务器,然后显示服务器发回来的内容。
下面程序在Ubuntu12.04系统中测试没有任何问题。
代码如下:
 

#include <stdio.h>
#include <stdio.h>
#include "debug.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <poll.h>
#include <sys/epoll.h>

typedef void (*a)(void);
typedef struct abc{
    a p;
    void *ptr;
    int sockfd;
}ABC;
void sock_handler(void)
{
    printf("my own socket handler\n");
}

int main()
{
    ABC ll;
    ll.p = sock_handler;
    ll.ptr = NULL;

    ll.p();
    int listenfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == listenfd)
        errsys("socket");

    struct sockaddr_in myaddr = {0};
    struct sockaddr_in clientaddr = {0};
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(8888);
    myaddr.sin_addr.s_addr = inet_addr("0.0.0.0");//INADDR_ANY
    int len = sizeof myaddr;

    if(-1 == bind(listenfd, (struct sockaddr*)&myaddr, len))
        errsys("bind");

    if(-1 == listen(listenfd, 10))
        errsys("listen");

    int epoll_fd = epoll_create(1024);
    if(-1 == epoll_fd)
        errsys("epoll");
            struct epoll_event event = {0};
    event.events = EPOLLIN;
    ll.sockfd = listenfd;
    event.data.ptr = (void*)&ll;
    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, listenfd, &event);

#define BUFSIZE 100
#define MAXNFD  1024 

    struct epoll_event revents[MAXNFD] = {0};
    int nready;
    char buf[MAXNFD][BUFSIZE] = {0};
    while(1)
    {
        if(-1 == (nready = epoll_wait(epoll_fd, revents, MAXNFD, -1)) )
            errsys("poll");


        int i = 0;
        for(;i<nready; i++)
        {
            if(revents[i].events & EPOLLIN)
            {
//      

                ABC *cc = (ABC *)revents[i].data.ptr;

                if(cc->sockfd == listenfd)
                {
                    int sockfd = accept(listenfd, (struct sockaddr*)&clientaddr, &len);
                    if(-1 == sockfd)
                        errsys("accept");
                    debug("incoming: %s\n", inet_ntoa( clientaddr.sin_addr) );

                    struct epoll_event event = {0};
                    event.events = EPOLLIN;
                    ABC ll;
                    ll.p = sock_handler;
                    ll.sockfd = sockfd;
                    event.data.ptr = (void*)&ll;
                    epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sockfd, &event);
                }
                else
                {
                    int ret = read(cc->sockfd, buf[cc->sockfd], sizeof buf[0]);
                    if(0 == ret)
                    {
            //          close(revents[i].data.fd);
                        epoll_ctl(epoll_fd, EPOLL_CTL_DEL, cc->sockfd, &revents[i]);

                    }

                    revents[i].events = EPOLLOUT;
//                  ABC *ll = (ABC *)revents[i].data.ptr;
                    epoll_ctl(epoll_fd, EPOLL_CTL_MOD, cc->sockfd, &revents[i]);
                }

            }
            else if(revents[i].events & EPOLLOUT)
            {
                ABC *ll = (ABC*)(revents[i].data.ptr);
                ll->p();
                int ret = write(ll->sockfd, buf[ll->sockfd], sizeof buf[0]);
                printf("ret %d: %d\n", ll->sockfd, ret);
                revents[i].events = EPOLLIN;
                epoll_ctl(epoll_fd, EPOLL_CTL_MOD, ll->sockfd, &revents[i]);
            }
        }
    }

    close(listenfd);
}

 client

#include <stdio.h>
#include "debug.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main(int argc, char **argv)
{
    if(3 != argc)
    {
        printf("Usage: %s <IP> <PORT>\n", argv[0]);
        return -1;
    }

    int sockfd = socket(AF_INET, SOCK_STREAM, 0); // 
    if(-1 == sockfd)
        errsys("socket");

    struct sockaddr_in serveraddr = {0};
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);//IPv4
    int len = sizeof serveraddr;

    if(-1 == connect(sockfd, (struct sockaddr*)&serveraddr, len))
        errsys("connect");

    char buf[100] = {0};
    while(1)
    {
        printf("mydatabase> ");fflush(stdout);
        gets(buf);
        int ret = write(sockfd, buf, sizeof buf);
        ret = read(sockfd, buf, sizeof buf);
        printf("%s\n", buf);
    }
    close(sockfd);
}

debug.h:

#ifndef _DEBUG_
#define _DEBUG_

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>

#ifdef DEBUG
    #define debug(arg...)  printf(arg)
#else
    #define debug(arg...)
#endif

#define errsys(str...) do{\
            fprintf(stderr, str);\
            fprintf(stderr, ": %s\n", strerror(errno));\
            exit(-1); \
            }while(0)

#endif

 

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页