我已经从外壳测试了该程序,并且从文件中还原标准输入时它可以正常工作。但是,当作为CGI程序运行时,它会超时(TimeForCGI hiawatha Web服务器设置设置为30秒)。该程序仅包含在一个文件中。应该注意的是,编写该程序仅是为了物理验证我在阅读的有关CGI的内容,并且我选择了C(或其他会生成二进制可执行文件的东西),因此我可以确保所有解释器都不会触及这些东西,可能会简化它们的抽象。
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <error.h>
int main (void);
int
main
(void)
{
static char buf[BUFSIZ];
size_t size;
if (setvbuf (stdout, NULL, _IOFBF, BUFSIZ) != 0)
error (EXIT_FAILURE, errno, "setvbuf(), stdout");
if (setvbuf (stdin, NULL, _IOFBF, BUFSIZ) != 0)
error (EXIT_FAILURE, errno, "setvbuf(), stdin");
if (setvbuf (stderr, NULL, _IOLBF, BUFSIZ) != 0)
error (EXIT_FAILURE, errno, "setvbuf(), stderr");
printf ("Content-Type: text/plain\n\n");
if (fflush (stdout) == EOF)
error (EXIT_FAILURE, errno, "fflush()");
for (;;)
{
size = fread (buf,1, BUFSIZ, stdin);
if (size == 0)
{
if (feof (stdin) != 0)
goto quit;
else
error (EXIT_FAILURE, errno, "fread(), stdin");
}
size = fwrite (buf, 1, size, stdout);
if (size == 0)
error (EXIT_FAILURE, errno, "write(), stdout");
}
quit:
fflush (stdout);
return EXIT_SUCCESS;
}
这是相应的html形式;
<html>
<head>
<title>Form</title>
</head>
<body>
<form action="form-process.cgi" method="post">
input_a: <input name="input_a" type="text"><br>
input_b: <input name="input_b" type="text"><br>
<input type="submit" value="Submit">
</form>
</body>
</html>
最佳答案
您的程序尝试从其标准输入中读取数据,直到到达结束为止。当您从文件重定向输入时,这很好,但是对于CGI程序是不合适的。当到达请求主体的末尾时,运行CGI的Web服务器没有义务在输入中发出文件结束信号。如果没有,则您的程序将在fread()
中无限期地阻塞。
有几个原因可能导致在请求正文末尾未发出EOF信号。 RFC明确地假设存在扩展数据,但是服务器将CGI的标准输入直接连接到将要发出请求的网络套接字也是合理的。在此之前,除非客户端关闭它,否则通常不会在其中检测到EOF。连接结束时,许多客户端在请求之间不执行此操作,其余客户端在收到响应后才执行其他操作。
因此,RFC 3875中的CGI规范说“即使有更多数据可用,脚本也绝不能尝试读取超过CONTENT_LENGTH个字节”(4.2节)。假设请求指定一个,则通过该名称的环境变量将CONTENT_LENGTH传送到脚本。您的CGI读取的字节数不得超过变量指定的字节数,并且,如果根本未指定内容长度,则它不得读取任何字节数。另一方面,不需要CGI读取整个请求正文或全部内容。
关于c - 从stdin/stdout读/写时,CGI程序超时,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/51699016/