poll2在与Web服务器的连接上未检测到POLLIN

问题描述

我目前正在用C编写一个小型项目,以更好地理解TCP,TLS,HTTP方法和C本身。

这是我程序的GET部分的简化代码段(无错误检查,已删除OpenSSL函数):

void htmlGET(char * path,char * address,int sockfd) {

    struct pollfd fds[1];
    fds[0].fd = sockfd;
    fds[0].events = POLLIN | POLLHUP | POLLERR;

    char * header;
    header = malloc(strlen(address)+50);
    sprintf(header,"GET %s HTTP/1.1\r\nHost: %s\r\n\r\n",path,address);
    
    write(sockfd,header,strlen(header));
    
    char buf[BUFSIZE];
    int rcount;
    
    while(1) {
        poll(fds,1,0);

        if (fds[0].revents & (POLLHUP | POLLERR)) { break; }

        else if (fds[0].revents & POLLIN){
            rcount = read(sockfd,buf,sizeof(buf));
            write(1,rcount);
        }
    }
}

我的程序执行GET请求并接收数据而无需轮询。但是,我发现某些网站会发送标头,然后在其他消息中发送其余的HTML,因此我决定实现轮询以接收所有内容。但是,每当我运行此代码时,该程序都会无限期地循环,并且我一直无法找到根本原因。关于可能出什么问题的任何建议吗?

更新:该程序似乎在一定程度上可以正常工作。我发现它确实在某个时间点完成,因此我决定在其上运行time(1)。这是一个示例结果:

3.33s user 23.74s system 20% cpu 2:14.94 total

关于为什么这么慢的任何想法?有时HTML会立即加载,程序会轮询很长时间,有时会轮询很长时间,然后HTML就会加载。

解决方法

关于:

poll(fds,1,0);

在MAN页面:

请注意,超时间隔将四舍五入到系统时钟 粒度和内核调度延迟意味着阻塞间隔可能会少量溢出。在中指定负值 超时意味着无限超时。 将超时指定为零会导致poll()立即返回,即使没有准备好文件描述符也是如此。(强调我的想法)

建议超时为负值,而不是0例如:-1

,

this帖子中,很明显,您不能指望Web服务器关闭与客户端的连接,因此使用轮询来确定何时停止从套接字读取并不是完整的解决方案。

我决定为Transfer-Encoding: ChunkedContent-Length: #合并消息头的解析。这为我提供了必要的信息,以确定是否已收到所有承诺的数据。

例如,使用Content-Length,我使用消息头以空白链接(\r\n\r\n)结尾的事实来确定消息正文的起始位置,然后计算接收到的字节数在缓冲区中,看看是否需要循环回去并再次读取身体的其余部分。

对于Transfer-Encoding: Chunked,我在相同的帖子和this指南上使用了建议,发现仅用0\r\n\r\n检查结尾块就可以了。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...