文章是网上内容总结,为了自己下次好找,所以写到自己博客里边了。
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 */
};
epoll_data中fd存放文件描述符,所以我们一般直接将监听的文件描述符赋值给epoll_event.data.fd,例如:
struct epoll_event event;
event.events=EPOLLIN;
event.data.fd = 0;//监听标准输入
可以看到,其中的data成员是一个联合体,其成员有一个void*的指针,还有一个fd,一般用法是直接把socket赋给fd即可,但是,有了这个void*的指针,我们就可以在注册socket的时候,传进我们想要的参数。在wait出来的时候,我们可以用我们自己的函数进行处理。
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传参。
下面是简单的demo代码,
server.c是一个简单的回射服务器,用于接收客户端发过来的数据,然后简单回发给客户端。
client.c是一个简单的客户端程序,由命令行参数输入IP和端口8888,由用户从键盘输入数据,直接发给服务器,然后显示服务器发回来的内容。
下面程序在Ubuntu12.04系统中测试没有任何问题。
Server.cpp
#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*)≪
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*)≪
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.cpp
#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