如何为套接字或 epoll 事件分配上下文 [英] how to assign a context to a socket or an epoll event

查看:52
本文介绍了如何为套接字或 epoll 事件分配上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用 epoll 编写一个基于事件的服务器.

I want to write an event based server using epoll.

每个客户端都有一个不同的请求,服务器应该响应它们.服务器将等待连接,当连接可用时,它们会排队等待读取.从客户端读取数据,它们将排队等待写入.处理完数据后,应向每个人发送适当的响应.

each client has a distinct request, and the server should respond to them. the server will wait for connections, and when connections are available they're queued for read. data is read from the clients and they'll be queued for write. after processing the data, an appropriate response should be sent to each.

所有操作都是异步的.

问题是,当套接字准备好写入时,我如何确定哪个响应是针对哪个套接字的?一种方式,我可以存储一个(套接字,数据)元组,但这是一种糟糕的编程.

the problem is, how can I determine, which response is for which socket when the sockets are ready for writing?? one way, I can store a (socket, data) tuple, but it's kind of bad programming.

我想知道是否可以为每个套接字或每个 epoll 事件分配一个上下文,以便确定哪些数据属于哪个套接字.

I wonder if I could assign a context to each socket, or each epoll event, so I could determine which data belongs to which socket.

有什么想法吗?

对于使用 SIGIO 而不是 epoll 有什么建议吗?如果我可以为文件描述符或信号分配上下文(我不熟悉 linux 编程),那么我可以无限期地休眠并等待信号......

is there any suggestions on using SIGIO instead of epoll? if I could assign a context to a file descriptor, or to a signal (I'm not familiar with linux programming) then I could sleep indefinitely and wait for signals...

现在忘记网络,看这个例子,我打开一个预先创建的FIFO,并暂停线程直到我得到一个SIGIO,在另一种情况下,考虑我打开10个FIFO并为每个分配一个随机数,当我想将该数字打印到控制台,不知何故我必须能够检索该数字,也许我可以为文件描述符分配一个上下文?

now forget about networking, look at this example, I open a pre-created FIFO, and pause the thread till I get a SIGIO, in another case, consider I opened 10 FIFO s and assigned a random number to each, when I want to print that number to console, somehow I must be able to retrieve the number, maybe I can assign a context to the file descriptor?

#include <stdlib.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <fcntl.h>
#include <signal.h>
#include <string.h>
static void sigioHandler(int sig)
{
}

int main()
{
    int fd, epfd, ret, i, nr_events, flags;
    struct sigaction sa;
    struct epoll_event event, *events;
    char buf[10];
    memset(buf, 0, 10);
    sa.sa_flags = SA_RESTART;
    sa.sa_handler = sigioHandler;
    if (sigaction(SIGIO, &sa, NULL) == -1)
    {
        perror("sigaction");
        exit(1);
    }
    events = malloc (sizeof (struct epoll_event) * 10);
    if (!events) {
          perror ("malloc");
          return 1;
  }

    fd = open("/tmp/foo", O_RDONLY);

    if(fcntl(fd, F_SETOWN, getpid())==-1){
        perror("own");
        exit(1);
    }
    flags = fcntl(fd, F_GETFL);
    if(fcntl(fd, F_SETFL, flags | O_ASYNC | O_NONBLOCK)==-1){
        perror("set");
        exit(1);
    }
    read(fd, buf, 10);
    epfd = epoll_create(10);
    if(epfd<0)
        perror("epoll_create");

    event.data.fd = fd;
    event.events = EPOLLIN | EPOLLET;

    ret = epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &event);
    if(ret)
        perror("epol_ctl");
    while(1){
        pause();
        nr_events = epoll_wait (epfd, events, 10, -1);
        if (nr_events < 0) {
            perror ("epoll_wait");
            free (events);
            return 1;
        }

        for (i = 0; i < nr_events; i++) {
            if(events[i].events & EPOLLIN)
            {
                read(events[i].data.fd, buf, 10);
                if(buf[0] == '#')
                    goto end;
                printf("%s", buf);
            }
        }
    }
end:
    free (events);

    close(epfd);
    close(fd);
    return 0;
}

稍微改变了一下:

static void sigioHandler(int status, siginfo_t *ioinfo, void * context)
{
    if(ioinfo == NULL)
        return;

    switch (ioinfo->si_code)
    {
        case POLL_IN:
            printf("signal received for input chars.sig:%d -%d\n",status, ioinfo->si_code);
            break;

        case POLL_OUT:
        default:
            printf("signal received for something else.sig:%d -%d\n",status, ioinfo->si_code);
            break;
    }
}

in main:
...
sa.sa_sigaction = sigioHandler;
...

我收到一个奇怪的分段错误.

I get a strange Segmentation Fault.

不知道FreeBSD的"mac_set_fd(int fd,mac_t label);"与此问题有关.

don't know if FreeBSD's "mac_set_fd(int fd, mac_t label);" is related to this problem.

推荐答案

您传递给 epoll_ctl() 并由 epoll_wait() 填充的 epoll_event 结构具有 data_ptr 字段.

The epoll_event structure that you pass to epoll_ctl(), and which is filled in by epoll_wait(), has a data_ptr field.

这篇关于如何为套接字或 epoll 事件分配上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆