在克奎尔(Kqueue)写一篇文章之前,请收到读取事件
我的代码有问题,我正在尝试使用MACOS上的C ++ 98创建HTTP服务器,并且我希望在写入之前执行读取的块,但相反的情况是知道为什么。 因此,我希望首先阅读请求,然后发送答复。但是这里发生了相反的情况, 这是我的代码:
/************************ 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班:
/***********************************************************************
* 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;
}
有人知道为什么在我的情况下阅读之前,我希望阅读请求,然后发送响应
I'm having an issue with my code, I'm trying to create an HTTP server using C++ 98 on MacOS, and I'm expecting the block of read to be executed before the write one, but the opposite is happening and I don't know why.
So I'm expecting to read first the request, then send a response. but the opposite is happening here,
this my code:
/************************ 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;
}
}
}
and kqueue class:
/***********************************************************************
* 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;
}
Does anyone know why the WRITE comes before the READ in my case, I'm expecting to read the request, then sending the response
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
为了使其可以从插座读取,首先,另一侧必须检测到连接已完成,然后必须构成其查询并将其放在电线上。然后,您的身边必须接收信息并处理信息。只有这样,才能从插座读取。
为了使其可以写入插座,您必须检测到连接已完成。就是这样。如果连接完成,则可以编写。
毫不奇怪,可以在插座上写入插座是可能的。问题是 - 当您不想写入套接字时,为什么您的代码检查是否可以写入套接字?另外,为什么您的代码仅仅是因为即使您甚至还没有从另一侧收到查询,也可以将代码写入套接字?
如果您没有数据写入另一侧,因为您甚至还没有从另一侧收到查询,为什么要检查是否可以在插座上写入?您不想写作,即使可能的话,为什么还要检查呢?
In order for it to be possible to read from the socket, first the other side has to detect that the connection is complete, then it has to compose its query and put it on the wire. Then your side has to receive the information and process it. Only then it is possible to read from the socket.
In order for it to be possible to write to the socket, you have to detect that the connection is complete. That's it. If the connection is complete, it's possible to write.
It's not surprising that it's possbile to write to the socket before it's possible to read from it. The question is -- why is your code checking if it's possible to write to the socket when you don't want to write to the socket? Also, why does your code write to the socket just because it's possible to do so even when you haven't even received a query from the other side?
If you have no data to write to the other side because you haven't even received a query from the other side yet, why are you checking whether or not it's possible to write on the socket? You don't want to write even if it's possible, so why check?