为什么Web服务器在发送响应之前应该清除套接字接收缓冲区?

时间:2018-10-26 09:09:14

标签: c sockets webserver

我正在研究一个小型Web服务器,它可以从浏览器接收GET请求并返回html文件。 serve_file函数将响应消息发送到浏览器,而get_line函数从套接字缓冲区获取一行。我不知道为什么必须读取并丢弃请求标头。我尝试在这两行中添加注释,然后浏览器显示一个连接重置页面。我猜服务器套接字的接收缓冲区已满,但是我不知道具体原因。有人可以解释吗?
source code

/* Send a regular file to the client.  Use headers, and report */

void serve_file(int client, const char *filename) {
    FILE *resource = NULL;
    int numchars = 1;
    char buf[1024];

    buf[0] = 'A'; buf[1] = '\0';

    //why?
    while ((numchars > 0) && strcmp("\n", buf))  /* read & discard request headers */
        numchars = get_line(client, buf, sizeof(buf));

    resource = fopen(filename, "r");
    if (resource == NULL)
        not_found(client);
    else {
        headers(client, filename); //send headers to tcp buffer
        cat(client, resource); //send index.html to tcp buffer
    }
    fclose(resource);
}

1 个答案:

答案 0 :(得分:0)

您观察到的行为是标准的套接字行为。

如果应用程序未读取从对等方接收的数据,并且应用程序在套接字上调用close,则OS不会执行通常的TCP连接终结操作。它立即重置连接,而不是完成连接。如果应用程序确实确实希望在接收到的缓冲区中有未读数据时正常关闭连接,则它必须在调用shutdown(socket, SHUT_WR)之前先调用close

为什么要以这种方式实现套接字API?因为这种处理可以避免dos攻击。如果close执行正常的TCP会话终结,则可能会受到以下攻击:

  • 恶意客户端打开TCP连接
  • 服务器接受连接并开始接收数据
  • 客户端发送连续的随机数据流
  • 服务器迅速检测到接收到的数据错误,并在套接字上调用close
  • close仅发送FIN,然后等待对等方关闭。服务器资源保持分配状态,因为常规FIN仅关闭了指向客户端的方向。客户端仍然可以发送数据,并且recv缓冲区不会被释放。

但是,当关闭启动连接重置时,与此TCP连接相关的资源将立即释放。这样一来,dos攻击就会变得更加复杂。

有关更多详细信息,请参见https://www.spinics.net/lists/linux-c-programming/msg01345.html