我正在 cpp 98 中编写一个简单的网络服务器,当我收到保持活动事件时,我没有关闭套接字并回收它,但已经设置为 EPOLLIN,因此 epoll_wait 将其返回,并在使用零字节进行一些读取后如果我在连接关闭的情况下在该袜子上重新发送请求,服务器崩溃一切都很好,我只需删除该事件(epoll_ctl EPOLL_CTL_DELL)?但套接字已经被接受,我不明白哪种是处理它的正确方法
这是主循环:
bool Webserver::_mainLoop() {
int eventNumber=0;
epoll_event events[MAX_EVENTS];
do{
// std::cout<<"main loop"<<std::endl;
eventNumber= epoll_wait(this->_epollFd,events,MAX_EVENTS,EPOLL_TIMEOUT);
std::cout<<RED<<"event number: "<<eventNumber<<RESET_COLOR<<std::endl;
if(eventNumber>0)
{
if(!_handleEpollEvents(eventNumber,events)) {
std::cout<<RED<<"Error handling epoll events"<<RESET_COLOR<<std::endl;
return false;
}
}
} while (eventNumber>=0);
std::cout<<RED<<"out of do while loop"<<RESET_COLOR<<std::endl;
if(eventNumber<0) {
std::cout<<RED<<"Error epoll wait"<<RESET_COLOR<<std::endl;
return false;
}
}
这是句柄事件:
bool Webserver::_handleEpollEvents(int &eventNumber, epoll_event (&events)[MAX_EVENTS]) {
std::cout<<BLUE<<"handling epoll events"<<RESET_COLOR<<std::endl;
for (int i = 0; i < eventNumber; ++i)
{
std::cout<<"handling event number: "<<i<<std::endl;
sType *type =static_cast<sType*>(events[i].data.ptr);
if(type->socketType==SERVER_SOCK)
{
Server *server = static_cast<Server *>(events[i].data.ptr);
if(!this->_acceptConnection(server))
{
std::cout<<"Error accepting connection"<<std::endl;
return false;
}
}else if(((events[i].events & EPOLLIN) || (events[i].events & EPOLLOUT)) && _handleConnection(events[i]) )
{
std::cout<<YELLOW<<"out of handling connection"<<RESET_COLOR<<std::endl;
return true;
}
}
return true;
}
这就是我现在处理保持活动的方法:
if(client.request()->connection()=="keep-alive"&& client.response()->complete()) {
std::cout<<GREEN<<"Connection keep-alive"<<RESET_COLOR<<std::endl;
if(client.request()){
delete client.request();
client.set_request(NULL);
}
if(client.response()){
delete client.response();
client.set_response(NULL);
}
struct timeval tv;
tv.tv_sec = 5;
tv.tv_usec = 0;
int flags = fcntl(client.getClientSock()->getFdSock(), F_GETFL, 0);
flags |= O_NONBLOCK;
fcntl(client.getClientSock()->getFdSock(), F_SETFL, flags);
if (setsockopt(client.getClientSock()->getFdSock(), SOL_SOCKET, SO_KEEPALIVE,(char *) &tv, sizeof(tv)) ==SOCKET_ERROR) {
std::cout<<RED << "cannot set socket option" << RESET_COLOR<<std::endl;
return false;
}
每次我读(recv)时,我都会用 EPOLL_CTL_MOD 从 epollin 更改为 epollout,每次写(发送)时反之亦然
这是我使用对 index.html 的 keep-alive get 请求来运行它时发生的事情的片段:
send 3251 bytes
Response ended set to epollin
k e e p - a l i v e
Connection keep-alive
Request : Destructor Called
Response : Destructor Called
out of handling connection
event number: 1
handling epoll events
handling event number: 0
handling connection
Request : Default Constructor Called
Response : Default Constructor Called
receiving data
client socket fd: 10
client socket service: 8090
client socket service: 127.1.0.1
client socket size: 16
Service sin family: 2
read 0 byte
Request ended set to epollout
response status code: 204client request connection:
The socket is in non-blocking mode
response:
�^ response size:4
send 4 bytes
Response ended set to epollin
response complete: truerequest error: false
connection: complete: true
event number: 1
handling epoll events
handling event number: 0
handling connection
ptr->socketType: 2
socket type: 2
Request : Default Constructor Called
Response : Default Constructor Called
receiving data
client socket fd: 10
client socket service: 8090
client socket service: 127.1.0.1
client socket size: 16
Service sin family: 2
read 0 byte
Request ended set to epollout
response status code: 204client request connection:
The socket is in non-blocking mode
response:
�^ response size:4
在此之后,如果需要,它会停止执行,代码位于 github 上的公共存储库上,但我不知道是否可以发布链接 也许响应中发送的 4 个字节是一个不为空的指针?不知道
很难理解你想要什么。但是您似乎假设 HTTP 请求中的“Connection: keep-alive”标头意味着某些保持活动的“事件”,服务器需要在发生时立即响应。
这个假设是错误的。 HTTP keep-alive 并不是某种需要响应的心跳。它只是意味着客户端可以在同一个 TCP 连接中处理多个请求。这意味着服务器可能(不是必须)在发送 HTTP 响应后保持 TCP 连接打开(一段时间),以便从客户端接收另一个 HTTP 请求。