1. 程式人生 > >epoll模型中struct epoll_event中data聯合體的用法

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