首页 > 解决方案 > Epoll反向代理在写客户端时卡住了

问题描述

我正在尝试使用非阻塞套接字和 epoll 编写反向代理。起初这似乎没问题,但是当我试图打开一个大的 jpg 文件时,我卡住了。当我有时尝试写入客户端时,它可能无法写入,我该如何正确处理。

补充说明:

this->getFd() = ProxyFd
this->clientHandler->getFd = clientFd

我正在使用EPOLLET代理和客户端的标志

   if( (flag & EPOLLIN) ){
        char buffer[1025] = {'\0'};
        int readSize;
        while( (readSize = read(this->getFd(),buffer,1024)) > 0){
            this->headerParse(buffer);
            this->readSize += readSize;
            int check = 0;
            do{
                check = write(this->clientHandler->getFd(),buffer,readSize);
            }while(check < 0);

        }
        if(this->headerEnd == 1 && this->readSize >= this->headerLenght  ){
            close(this->clientHandler->getFd());
            close(this->getFd());
            delete this->clientHandler;
            delete this;
        } 
    }

感谢您花时间阅读。

标签: c++csocketsreverse-proxyepoll

解决方案


假设您的 headerParse() 方法不会以扩展大小的方式更改缓冲区(您至少需要更新 readsize,更不用说缓冲区已满的情况),您的 write() 路径似乎已损坏。

如果您正在写入的套接字也处于非阻塞模式,那么 write() 在写入所有数据之前返回 -1(并将 errno 设置为 EGAIN 或 EWOULDBLOCK 或您的平台具有的任何内容)是完全合法的。在这种情况下,您必须存储剩余的数据(如果一个或多个 write() 调用成功,则缓冲区的剩余部分减去写入的内容),编程 epoll 以通知 clientHandler->getFd() 描述符的可写性,如果还没有,当您获得后续的“写入就绪”事件时,您将写入您存储的数据。在这种情况下, write() 可能再次无法刷新所有数据,因此您必须循环直到发送所有数据。


推荐阅读