Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/linux/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Linux 如何为套接字或epoll事件分配上下文_Linux_Sockets_Networking_Signals_Epoll - Fatal编程技术网

Linux 如何为套接字或epoll事件分配上下文

Linux 如何为套接字或epoll事件分配上下文,linux,sockets,networking,signals,epoll,Linux,Sockets,Networking,Signals,Epoll,我想使用epoll编写一个基于事件的服务器 每个客户端都有一个不同的请求,服务器应该响应它们。 服务器将等待连接,当连接可用时,它们将排队等待读取。 数据是从客户端读取的,它们将排队等待写入。 在处理数据后,应向每个人发送适当的响应 所有操作都将是异步的 问题是,当套接字准备好写入时,如何确定哪个响应是针对哪个套接字的?? 一种方法是,我可以存储(套接字、数据)元组,但这是一种糟糕的编程 我想知道是否可以为每个套接字或每个epoll事件分配一个上下文,以便确定哪些数据属于哪个套接字 有什么想法吗

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

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

所有操作都将是异步的

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

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

有什么想法吗

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

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

#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;
}
我有一个奇怪的分段错误


不知道FreeBSD的“mac_set_fd(int fd,mac_t label);”是否与此问题有关。

关于您的第一个问题,我尝试过这样的方法,并且效果良好。 对于您与其他对等方的每个连接(假设您使用的是TCP),您都有一个新的文件描述符。因此,每个连接通过描述符是唯一的


在我的项目中,我使用了select。必须添加描述符,这些描述符是使用FD_SET连接()的结果。有关更多信息,请参阅select的Linux手册页。

关于您的第一个问题,我已经尝试过这样的方法,而且效果很好。 对于您与其他对等方的每个连接(假设您使用的是TCP),您都有一个新的文件描述符。因此,每个连接通过描述符是唯一的


在我的项目中,我使用了select。必须添加描述符,这些描述符是使用FD_SET连接()的结果。有关更多信息,请参阅select的Linux手册页。

传递给epoll_ctl()的、由epoll_wait()填写的epoll_事件结构有一个data_ptr字段。

传递给epoll_ctl()的、由epoll_wait()填写的epoll_事件结构,有一个数据ptr字段。

正如Benito指出的,传递到epoll\u ctl的epoll\u事件结构有一个数据ptr字段。要完全正确,创建上下文所使用的字段定义为

typedef union epoll_data 
    void        *ptr;
    int          fd;
    uint32_t     u32;
    uint64_t     u64;
} epoll_data_t;
i、 e.工会。在许多示例中,fd字段通常用于上下文。但是我发现PTR字段在C++中最有用,它可以用来指向包含套接字或连接的所有状态的对象。 如果你有一个像这样的物体:

class Connection
{
  private:
    int m_fd;

  public:
    Connection(int fd) : m_fd(fd) {}

    // Other methods like Send/Receive
};


/////
// Somewhere in your server accept loop for a server
struct sockaddr sin;
socklen_t len = sizeof(sin);
int fd = accept(s_listen, &sin, &len);
if (fd == -1) {
    // handle error
}

// or if it's a client you'd have just created the socket with a call to socket()

// and then you add the new connection to epoll.
epoll_event ev;
ev.data.ptr = new Connection(fd);
ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;    
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
    ; // handle error
}
类连接
{
私人:
国际货币基金组织;
公众:
连接(int-fd):m_-fd(fd){}
//其他方法,如发送/接收
};
/////
//服务器的服务器接受循环中的某个位置
结构sockaddr-sin;
socklen_t len=sizeof(sin);
int fd=accept(s_listen,&sin,&len);
如果(fd==-1){
//处理错误
}
//或者,如果它是一个客户机,您可以通过调用socket()创建套接字
//然后将新连接添加到epoll。
epoll_事件ev;
ev.data.ptr=新连接(fd);
ev.events=EPOLLIN | epollut | epolldhup;
如果(epoll控制(epfd、epoll控制添加、fd和ev)<0){
;//句柄错误
}

稍后,当您使用epoll_wait获取epoll事件时,您可以访问event.data.ptr并将其转换回连接类型,并调用默认方法来处理事件。然后,该类可以调用适当的方法来完成读/写等工作。

正如Benito指出的,传递到epoll\u ctl的epoll\u事件结构有一个data\u ptr字段。要完全正确,创建上下文所使用的字段定义为

typedef union epoll_data 
    void        *ptr;
    int          fd;
    uint32_t     u32;
    uint64_t     u64;
} epoll_data_t;
i、 e.工会。在许多示例中,fd字段通常用于上下文。但是我发现PTR字段在C++中最有用,它可以用来指向包含套接字或连接的所有状态的对象。 如果你有一个像这样的物体:

class Connection
{
  private:
    int m_fd;

  public:
    Connection(int fd) : m_fd(fd) {}

    // Other methods like Send/Receive
};


/////
// Somewhere in your server accept loop for a server
struct sockaddr sin;
socklen_t len = sizeof(sin);
int fd = accept(s_listen, &sin, &len);
if (fd == -1) {
    // handle error
}

// or if it's a client you'd have just created the socket with a call to socket()

// and then you add the new connection to epoll.
epoll_event ev;
ev.data.ptr = new Connection(fd);
ev.events = EPOLLIN | EPOLLOUT | EPOLLRDHUP;    
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
    ; // handle error
}
类连接
{
私人:
国际货币基金组织;
公众:
连接(int-fd):m_-fd(fd){}
//其他方法,如发送/接收
};
/////
//服务器的服务器接受循环中的某个位置
结构sockaddr-sin;
socklen_t len=sizeof(sin);
int fd=accept(s_listen,&sin,&len);
如果(fd==-1){
//处理错误
}
//或者,如果它是一个客户机,您可以通过调用socket()创建套接字
//然后将新连接添加到epoll。
epoll_事件ev;
ev.data.ptr=新连接(fd);
ev.events=EPOLLIN | epollut | epolldhup;
如果(epoll控制(epfd、epoll控制添加、fd和ev)<0){
;//句柄错误
}

稍后,当您使用epoll_wait获取epoll事件时,您可以访问event.data.ptr并将其转换回连接类型,并调用默认方法来处理事件。然后,该类可以调用适当的方法来完成读/写等工作。

正如我提供的源代码所示,将文件描述符添加到epoll上下文没有问题,问题是,我想用每个文件描述符保存其他信息,在内核编程中,使用对象保存用户定义的上下文是一种常见的方法,我希望这里的功能与您在我提供的源代码中看到的相同,向epoll上下文添加文件描述符没有问题,问题是,我想用每个文件描述符保存附加信息,在内核编程中,保存用户定义的上下文是一种常见的方法