我有一个用 C 编写的 CGI 程序,它从客户端的 curl 读取 PUT 请求,并将上传的文件复制到服务器上的目录。这一切都很好。
问题是,如果出现问题,我需要一种取消正在进行的上传的方法,例如,如果用户的存储空间已超出。我似乎无法通过简单地从 CGI 程序返回来做到这一点。 curl 继续尝试上传文件,所以在大文件上,我必须等待它发送整个文件(或认为它正在发送整个文件),然后它才会读取告诉它“否”的服务器响应。
有没有办法退出CGI程序并终止连接而不必等待PUT请求完成?
是的,有很多方法可以在不等待 PUT 请求完成的情况下从服务器端取消正在进行的上传
一种方法是在上传文件时向客户端发送 HTTP 错误代码。当客户端收到错误代码时,会立即停止上传过程。为此,您可以使用标准 C 库函数 printf 来输出相应的 HTTP 错误代码和消息。例如,要向客户端发送“413 Request Entity Too Large”错误,您可以这样做:
printf("Status: 413 Request Entity Too Large\r\n\r\n");
fflush(stdout);
需要fflush调用来保证消息立即发送到客户端,而不用等待请求结束
另一种取消上传的方法是在退出CGI程序前,使用setsockopt函数将socket上的SO_LINGER选项设置为非零值。这将导致 TCP 连接立即关闭,从而中止上传过程。这是一个例子:
struct linger linger = {1, 0};
setsockopt(fileno(stdout), SOL_SOCKET, SO_LINGER, &linger,
sizeof(linger));
exit(0);
这将 SO_LINGER 选项设置为超时为 1 秒的结构逗留,这意味着套接字将在关闭调用后逗留最多 1 秒,直到所有未决数据已发送或超时已过期。
请注意,第二种方法可能不适用于所有系统,因为某些 TCP/IP 堆栈可能会在套接字处于非阻塞状态时忽略 SO_LINGER 选项(CGI 程序通常是这种情况)。第一种方法通常更可靠,但可能需要 CGI 程序和客户端之间更多的协调。