sleep(1)+ fflush(stdout)通过curl工作。不是通过网络浏览器

时间:2017-07-05 07:08:22

标签: c cgi

暂停(sleep(1)),通过curl命令运行脚本时工作正常 而不是在网络浏览器上运行。

但是通过网络浏览器..它会暂停所有暂停的总和(3 x sleep(1)),然后一次打印所有暂停

可以采取哪些措施来确保网络浏览器的行为像卷曲一样?

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main() {
    printf("Content-type: text/plain\n\n");

    printf("%s\n", "test 1");
    fflush(stdout);

    sleep(1);

    printf("%s\n", "test 2");
    fflush(stdout);

    sleep(1);

    printf("%s\n", "test 3");
    fflush(stdout);

    sleep(1);

    printf("%s\n", "test 4");
    fflush(stdout);

    return 0;
}

2 个答案:

答案 0 :(得分:2)

HTTP最初旨在提供文档。它有一个描述文档的标题,文档本身跟在主体中,通常都是一个整体。

其中一个标题是Content-Length:,包含正文的大小,因此客户端知道要预期的数据量。浏览器通常会在开始显示之前尝试获取整个文档。在您的示例中,没有Content-Length:,浏览器只是等待连接关闭。

当然,设置Content-Length: 可以帮助您,浏览器仍然会等待整个文档。但是还有chunked transfer encoding用于分发多个文件。您可以自己实施,例如像这样:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
    char buffer[1024];

    // note that "Content-Type" has an uppercase T, be exact when
    // implementing a protocol!
    printf("Content-Type: text/plain\n");
    printf("Transfer-Encoding: chunked\n\n");    

    // snprintf() just for demonstration, you might need it for output
    // of anything more complex than just fixed strings.
    snprintf(buffer, 1024, "%s", "test 1");

    // size of next chunk:
    printf("%zx\n", strlen(buffer));

    printf("%s\n", buffer);

    fflush(stdout);
    sleep(1); // or something more sensible, like, actual work...

    // more data, finally indicate this was the last chunk:
    printf("\n");

    return 0;
}

关于此解决方案可行性的一些注意事项:

  • 使用CGI,如此处所示,“脚本”的运行持续时间通常有限制。可以在没有时间限制的情况下配置Web服务器,否则这将只会遇到CGI超时。更好的解决方案是将其编写为自托管Web服务,有关某些链接,请参阅Basile's answer

  • 这种方法的好处在于它不需要客户端代码,因此它几乎适用于任何浏览器(分块传输支持非常常见)。缺点是由于某些环境条件可能导致TCP连接松动,唯一的恢复方法是手动重新加载页面。因此,您可能想要使用javascript (如果可用)并转到WebSockets(最好看看Basile的回答),如果不可用,请执行long polling

答案 1 :(得分:1)

HTTP比您认为的要复杂得多,而且CGI已过时(使用HTML5和AJAX应用程序)。考虑使用某些 HTTP服务器库,如libonion (或制作FastCGI应用程序...)和/或某些 HTTP客户端库,如libcurl < /强>

为了让您的工作没有任何库(IMHO是一个错误),您需要学习更多HTTP并添加more headers in your HTTP request,特别是Host:,并在响应中:Content-Length:Connection: close

我强烈建议您不要自行编码所有HTTP协议(因此使用HTTP库)。

  

可以采取哪些措施来确保网络浏览器的行为像卷曲一样?

什么都做不了;浏览器有权仅处理完整的 HTTP消息,并且有充分的理由。此外,大多数浏览器会打开多个连接(同时)到相同的 HTTP服务。

如果您需要现代浏览器的明显交互行为(即随着时间的推移而视觉上发展的浏览器窗口),您应该考虑使用AJAX(带HTML5)和&amp; WebSockets,因此使用JavaScript(可能在服务器端生成)对浏览器进行编程。另请阅读single-page applications。查看websocket example of libonion(它可能与您的需求非常相关)。 BTW这样的WebSockets&amp; AJAX&amp;基于HTML5的方法具有(超过answer provided by Felix Palmen)优势,可以实现更具视觉效果的内容(例如计算和显示行号),以及(使用一些额外的Javascript代码)添加清除显示的日志行的功能(仅限浏览器方面)。

BTW,特别是在Linux上(使用像ext4这样的本地文件系统),您可能希望使用inotify(7)工具来通知文件更改。您需要event loop poll(2)左右(或较旧的select(2) ...),但大多数与HTTP相关的库都会提供一个。{/ p>

重要的是要理解 HTTP 是交互式协议(每个请求都是浏览器启动并且只获得一个响应)。要添加交互性(流向服务器),您需要更多(例如,WebSockets,它提供从服务器到浏览器的异步消息),或者至少一些“半忙碌轮询”,这是定期的Javascript(在浏览器)做AJAX请求。