[英]How to access user-context data set on epoll when calling epoll_wait
Below I add sockets to epoll and set an application-context index within epoll_event.data.u32
.下面我将套接字添加到 epoll 并在
epoll_event.data.u32
设置应用程序上下文索引。
When receiving packets, recv()
requires the socket file descriptor.接收数据包时,
recv()
需要套接字文件描述符。 In all the examples events[i].data.fd
is used.在所有示例中都使用了
events[i].data.fd
。
However, events[i].data.fd
and events[i].data.u32
are in a union, so how do I also access my user-context index events[i].data.u32
?但是,
events[i].data.fd
和events[i].data.u32
是联合的,那么我如何访问我的用户上下文索引events[i].data.u32
? It looks like it is overwritten with the socket file descriptor?看起来它被套接字文件描述符覆盖了?
// Initially
int epollFd = epoll_create1(0);
// Adding each socket, along with a user-context index for callbacks
struct epoll_event event;
event.events = EPOLLIN;
event.data.u32 = callbackIndex; // Here is the user-defined index
int sock = createSocket(port, address);
assert(epoll_ctl(epollFd, EPOLL_CTL_ADD, sock, &event));
// Later when receiving packets
struct epoll_event events[MAX_EVENTS];
while (true)
{
int event_count = epoll_wait(epollFd, events, MAX_EVENTS, 30000);
for (i = 0; i < event_count; i++)
{
int n = recv(events[i].data.fd, &buffer[0], sizeof(buffer), flags);
// How do I access the user-context index I set when adding the socket to epoll?
}
}
You tell epoll_ctl()
which socket descriptor you want to listen for events for, and provide an epoll_event
struct to associate with that listen operation.你告诉
epoll_ctl()
你想要监听哪个套接字描述符,并提供一个epoll_event
结构来与监听操作相关联。
Whenever epoll_wait()
detects a registered event on a socket, it gives you back only the epoll_event
struct that you had provided for that event, exactly as you had provided it.每当
epoll_wait()
检测到套接字上的注册事件时,它只会返回您为该事件提供的epoll_event
结构,与您提供的完全一样。 It does not tell you which socket triggered the event.它不会告诉您哪个套接字触发了事件。
So, if you want to discover the socket, you have to either:因此,如果您想发现套接字,您必须:
store the socket descriptor itself in the epoll_event
, but then you can't use any other user-defined data.将套接字描述符本身存储在
epoll_event
,但是您不能使用任何其他用户定义的数据。
store the socket descriptor somewhere else (ie, in an array, an object pool, etc) and then put identifying information needed to get back to the socket descriptor as user-defined data in the epoll_event
(ie, array index, object pointer, etc).将套接字描述符存储在其他地方(即,在数组、对象池等中),然后将返回套接字描述符所需的标识信息作为用户定义的数据放在
epoll_event
(即,数组索引、对象指针等) )。
Whatever you put in the epoll_event
when calling epoll_ctl()
is what you will get back from epoll_wait()
.调用
epoll_ctl()
时在epoll_event
放入的epoll_event
都是从epoll_wait()
。 No more, no less.不多也不少。
Design of epoll is beautifully simple. epoll 的设计非常简单。 The role of
epoll_data_t
is to provide lightweight mapping rather than storage . epoll_data_t
的作用是提供轻量级映射而不是存储。 Notice that it has a void* ptr
member, which allows you to map from fd
(passed to epoll_ctl
) to anything .请注意,它有一个
void* ptr
成员,它允许您从fd
(传递给epoll_ctl
)映射到任何东西。
In your particular case, you could allocate a struct Context { int fd; uint32_t index; /*...*/ };
在您的特定情况下,您可以分配一个
struct Context { int fd; uint32_t index; /*...*/ };
struct Context { int fd; uint32_t index; /*...*/ };
on the heap and point to that structure on EPOLL_CTL_ADD
.在堆上并指向
EPOLL_CTL_ADD
上的该结构。 You would have to also deallocate it after calling EPOLL_CTL_DEL
by some object (eg container) which owns that context.在通过拥有该上下文的某个对象(例如容器)调用
EPOLL_CTL_DEL
之后,您还必须取消分配它。
Since you are using C++, you could store a pointer to an abstract EventListener
base class, reinterpret_cast
from void*
after epoll_wait
to that class and dispatch event to an arbitrary derived handler.由于您使用C ++,你可以存储指向一个抽象的
EventListener
基类reinterpret_cast
从void*
后epoll_wait
的那类和分派事件到任意来源的处理程序。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.