我必须(作为一项任务)用 C 语言编写一个小型 HTTP/1.0 服务器。
这是我的问题:我不知道如何处理客户端请求的页面尺寸非常大的情况。
我认为最好先读取整个文件,然后开始向客户端发送回复(包括状态行和标题),主要原因是我可以适本地设置状态码。例如,假设服务器已经读取并存储为客户端想要的文件的一半字符串,read()
失败。然后我会继续并将“HTTP/1.0 500 内部服务器错误”设置为状态行。
这种方法的问题是,如果文件很大,它会占用太多内存(并且由于每个连接都由一个单独的线程处理,如果多个线程要将相当大的文件存储为字符串,内存使用量会增加更糟)。
作为一个解决方案,我考虑打开文件,发送状态行和标题,然后将给定数量(不要太大)的字节读入缓冲区并迭代发送缓冲区中的内容,直到我读取/发送了整个文件。
这解决了问题,但是,如果 read()
在我读到文件的一半时失败怎么办?由于内部错误,客户端请求无法完成,因此 500 状态代码是合适的,但我已经通过套接字发送了 200 OK 消息!
HTTP 服务器通常如何处理这个问题?
最佳答案
As a solution I thought about opening the file, sending the status line and the headers, then read into a buffer a given amount (not too large) of bytes and iteratively send what is in the buffer until I've read/sent the whole file.
这正是您应该做的。事先查询文件大小,以便将其放入 Content-Length
响应 header ,然后在发送了那么多字节后停止读取+发送循环。
如果您可以切换到 HTTP 1.1,那么您还有另一种选择。您可以省略 Content-Length
header ,而是发送 Transfer-Encoding: chunked
header ,然后您可以以 chunked
格式发送每个缓冲区(参见 RFC 2616 Section 3.6.1 ),其中每个 block 指定其自己的字节大小。数据传输通过发送一个 0 长度的 block 来终止。这允许您在不知道总大小的情况下发送/流式传输大量数据。但是这个选项在 HTTP 1.0 中不可用。
This solves the problem, but again, what if read() fails while I'm halfway through the file?
您唯一能做的就是关闭套接字以表示传输已终止。如果您发送一个 Content-Length
header (或者在 HTTP 1.1 分块的情况下,发送一个 0 长度的 block ),客户端将知道它何时收到正确的文件结尾,以及过早的关闭是一个错误。但是如果没有这些信息,套接字关闭是表示传输结束的唯一方法,客户端将无法知道它是成功还是错误(HTTP 1.1 确实有能力恢复中断的下载,但是HTTP 1.0 没有)。
The client request could not be fulfilled because of an internal error, thus a 500 status code would be appropriate, but I've already sent a 200 OK message through the socket!
一旦发送,您就无法更改回复状态。但是,如果您让客户端知道它如何检测文件的正确结尾,它就会知道如何检测损坏的下载。
关于c - C中的HTTP/1.0服务器,如何向客户端发送大文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36096926/