首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >事件在kqueue中的写入事件之前接收到。

事件在kqueue中的写入事件之前接收到。
EN

Stack Overflow用户
提问于 2022-05-16 23:44:50
回答 1查看 73关注 0票数 0

我的代码出了问题,我试图在MacOS上使用MacOS 98创建一个HTTP服务器,我希望在写代码之前执行读块,但是相反的情况正在发生,我不知道为什么。所以我希望先读一下请求,然后发送回复。但相反的情况是,这是我的代码:

代码语言:javascript
复制
/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Server::Server(int addr, int port)
{
    this->sock.create_socket(AF_INET, SOCK_STREAM, 0);
    this->sock.bind_socket(addr, port);
    this->sock.listen_socket(__MAX_BACKLOG__);
}

webserv::Server::~Server() {}

/************************ MEMBER FUNCTION ************************/
void    webserv::Server::lunch()
{
    this->kq.create_event(this->sock.getSocket(), EVFILT_READ);
    while (1)
        this->_lunch_worker();
}

void    webserv::Server::_lunch_worker(void)
{
    int ev_count = this->kq.get_event();
    static const char* index_html = "HTTP/1.0 200 OK\r\n" \
                                    "Content-Length: 86\r\n\r\n" \
                                    "<!DOCTYPE html>" \
                                    "<html><head>Hello, world!</head><body><h1>cdn-ish...</h1></body></html>\r\n";
    char buf[10000];

    for (int i = 0; i < ev_count; i++) {
        int fd = this->kq.get_fd(i);

        if (fd < 0) continue;
        if (fd == this->sock.getSocket()) {
            
            int clientaddr_size = sizeof(this->sock.getAddress());

            int clientfd = this->sock.accept_socket();
            if (clientfd < 0) {
                perror("accept");
                close(fd);
                return ;
            }
            this->kq.create_event(clientfd, EVFILT_READ);
            if (fcntl(clientfd, F_SETFL, O_NONBLOCK) < 0) {
                perror("fcntl");
                close(clientfd);
                close(fd);
            }
            this->kq.create_event(clientfd, EVFILT_WRITE, EV_ADD | EV_ONESHOT);
        // EXPECTING THIS BLOCK TO BE CHECKED/EXECUTED FIRST
        // BUT INSTEAD THE NEXT BLOCK (WRITE BLOCK) IS EXECUTED FIRST
        // THEN IN THE SECOND ITERATION THE READ BLOCK IS BEING EXECUTED
        } else if (this->kq.is_read_available(i)) {
            int len;
            std::cout << "READ" << std::endl;
            // memset(buf, 0, sizeof(buf));
            if ((len = recv(fd, buf, sizeof(buf), 0)) == 0) {
                std::cout << "READ: FD CLOSED = " << fd << std::endl;
                close(fd);
            }
            else if (len > 0)
            {
            }
            std::cout << "READ: LEN = " << len << std::endl;
        } else if (this->kq.is_write_available(i)) {
            int len = 0;
            if ((len = send(fd, index_html, strlen(index_html), 0)) != 0) {
            }
            std::cout << "WRITE: LEN = " << len << std::endl;
        }
    }
}

和kqueue类:

代码语言:javascript
复制
/***********************************************************************
* FILENAME :        Kqueue.cpp
*
* DESCRIPTION :
*       This File is the implementation of the functions
*       Defined in Kqueue.hpp
*
**/

# include "./Kqueue.hpp"
# include "../../OutputColors.hpp"

/************************ CONSTRUCTORS/DESTRUCTOR ************************/
webserv::Kqueue::Kqueue()
{
    this->_kq = kqueue();
    std::cout << "KQUEUE CREATED" << std::endl;
    this->test_error(this->_kq, "Creating Kqueue :");
    this->_n_ev = 0;
}

webserv::Kqueue::~Kqueue()
{
    close(this->_kq);
}

/************************ MEMBER FUNCTIONS ************************/
void    webserv::Kqueue::set_event(int fd, int filter, int flags, void *udata)
{
    EV_SET(&this->_ev_set, fd, filter, flags, 0, 0, udata);
}

void    webserv::Kqueue::add_event(void)
{
    int ret;

    ret = kevent(this->_kq, &this->_ev_set, 1, NULL, 0, NULL);
    this->test_error(ret, "Kqueue/add_even functions");
}

int     webserv::Kqueue::get_event(void)
{
    this->_n_ev = kevent(this->_kq, NULL, 0, this->_ev_list, __EV_LIST_SIZE__, NULL);
    this->test_error(this->_n_ev, "Kqueue/get_event function:");
    return (this->_n_ev);
}

void    webserv::Kqueue::create_event(int fd, int filter, int flags, void *udata)
{
    this->set_event(fd, filter, flags, udata);
    this->add_event();
}

bool    webserv::Kqueue::isEOF(int index)
{
    if (this->_n_ev <= index)
        this->test_error(-1, "Kqueue/isEOF function:");
    return (this->_ev_list[index].flags & EV_EOF);
}

bool    webserv::Kqueue::is_read_available(int index)
{
    if (this->_n_ev <= index)
        this->test_error(-1, "Kqueue/is_read_available function:");
    return (this->_ev_list[index].filter == EVFILT_READ);
}

bool    webserv::Kqueue::is_write_available(int index)
{
    if (this->_n_ev <= index)
        this->test_error(-1, "Kqueue/is_write_available function:");
    return (this->_ev_list[index].filter == EVFILT_WRITE);
}

void    webserv::Kqueue::test_error(int fd, const std::string &str)
{
    if (fd < 0)
    {
        std::cerr << RED << str << " ";
        perror("The following error occured: ");
        std::cerr << RESET;
        exit(EXIT_FAILURE);
    }
}

/************************ GETTERS/SETTERS ************************/
struct kevent   *webserv::Kqueue::get_event_list()
{
    return (this->_ev_list);
}

int &webserv::Kqueue::get_kq()
{
    return (this->_kq);
}

int             webserv::Kqueue::get_fd(int index)
{
    if (this->_n_ev <= index)
        this->test_error(-1, "Kqueue/get_ev_list function:");
    return (this->_ev_list[index].ident);
}

void    webserv::Kqueue::set_kqueue(int fd)
{
    this->_kq = fd;
}

有人知道为什么写在读之前吗?在我的例子中,我希望读取请求,然后发送响应

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-05-16 23:49:20

为了能够从套接字中读取数据,另一方必须首先检测连接是否完成,然后才能组合其查询并将其放到线路上。然后你的一方必须接收信息并处理它。只有这样,才有可能从套接字中读取。

为了能够写入套接字,您必须检测连接是否已完成。就这样。如果连接完成,则可以编写。

这是不足为奇的,它是拥有写到插座之前,它是可能的阅读。问题是--为什么当您不想写入套接字时,您的代码要检查是否可以写入套接字?此外,为什么您的代码写到套接字仅仅是因为它是有可能这样做,即使你还没有收到来自另一方的查询?

如果由于还没有收到来自另一方的查询,所以没有数据可以写入另一方,为什么要检查是否可以在套接字上写入?即使有可能,你也不想写,那么为什么要检查呢?

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72266716

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档