暂停(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;
}
答案 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请求。