epoll模型中struct epoll_event中data聯合體的用法

在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系統中測試沒有任何問題。
代碼如下:
server.c:

#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.c:

#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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章