我正在编写自己的HTTP客户端和服务器,并希望客户端在请求中包含一个可选的主体。在服务器端,我想在发送HTTP响应之前读取整个正文。我的问题是在服务器上我怎么知道我已经阅读了整个身体?
即使在这种情况下我控制客户端和服务器,我正在寻找一种“标准”方法。但是,由于Content-Length是可选的,我想要一个不需要它的方法。如果客户端关闭连接,则很容易读取所有可用数据,但客户端需要保持连接打开以等待响应,因此此方法不起作用。
我能想到的只有身体的格式和检测终结者的知识(例如</HTML>
)。理想情况下,我不想要这些知识。
我有什么方法可以忽略吗?
答案 0 :(得分:50)
假设您希望您的客户端与其他服务器一起工作,并且服务器与其他客户端一起工作,那么您的服务器将无法得到很好的处理。
有两种方法可以判断身体何时结束。他们都不需要知道正文的内容类型(例如,不要费心寻找</html>
- 远远超出HTTP协议)。
Transfer-Encoding: Chunked
,则需要解析有些复杂的chunked transfer encoding syntax。你真的没有多少选择 - 如果客户端以这种格式发送,你必须收到它。当客户端使用此方法时,您可以通过长度为0的块检测正文的结尾。Content-Length
,则必须使用该帐户。正如您所建议的,检测结束的第三种方法 - 连接关闭时 - 仅适用于响应,而不适用于请求(因为没有办法发送响应)。
答案 1 :(得分:22)
If a request contains a message-body and a Content-Length is not given,
the server SHOULD respond with 400 (bad request) if it cannot determine
the length of the message, or with 411 (length required) if it wishes
to insist on receiving a valid Content-Length.
即。您有权坚持Transfer-Encoding: chunked
或Content-Length
,因此您无需担心在任何其他情况下确定长度
答案 2 :(得分:9)
我添加另一个答案主要是因为我没有足够的代表来评论 mgiuca 。我知道这个问题有点陈旧但没有明确的答案。
正如提到的那样,要考虑的主要事情是您的服务器与无法控制的其他人进行交互,这意味着无法知道他们将发送的内容 at所有,并且必须准备好管理通过那个门的任何东西。考虑到这一点,坚持标准和常规做法可能是最好的选择。
如果客户发送&#34; Content-Length&#34;标头,服务器必须解析它并使用它来确定请求的结束。如果没有这样的标题,那么&#34;转移编码:chunked&#34;如果存在标头,则服务器必须能够解析分块请求(link来自 mgiuca 的答案)。最后,如果两者都不存在,&#34;连接结束&#34;发出请求结束的信号。
我认为您忽略的是客户端可以结束连接并仍然从服务器获得响应。我的意思是,&#34;结束连接&#34;意思?请记住,HTTP是一种通常通过TCP传输的应用层协议。探索TCP的功能(特别是其connection termination协议)揭示了一些有趣的信息:
但它确实存在!客户已通知他想要终止连接,服务器知道,但是客户端仍然打开了连接(他还没有关闭它,因为他没有收到 FIN 数据包)。服务器现在应答请求,然后正确关闭连接。值得注意的是,客户端将确认每个服务器数据包并附加 RST 标志,告诉服务器他仍然期待 FIN 关闭连接。
当服务器完成时(在我们的小例子中,在发送HTTP响应之后),他关闭了他身边的连接,发送了 FIN 数据包。客户收到后会关闭他的一方,并通过 ACK 通知服务器。
另外请注意,我不知道您编程的上下文,但大多数时候您最终会在套接字上调用 shutdown()。 POSIX's shutdown(至少Windows')将要关闭的连接接口作为函数参数。这些规范清楚地表明您可以关闭发件人部分(这正是客户端将要做的事情),禁用数据发送,同时允许客户端接收更多数据。
有关TCP连接的更多详细信息超出了这个问题的范围,但我建议阅读它以更好地理解使用它的更高层的协议。
答案 3 :(得分:5)
简单方法:使用HTTP 1.0并要求内容长度
为了与HTTP / 1.0应用程序兼容,包含消息体的HTTP / 1.1请求必须包含有效的Content-Length头字段,除非已知服务器符合HTTP / 1.1。如果一个请求包含一个消息体并且没有给出Content-Length,那么服务器应该响应400(错误的请求),如果它不能确定消息的长度,或者如果它希望坚持,则应该使用411(需要的长度)收到有效的内容长度。
答案 4 :(得分:2)
当你说“Content-Length是可选的”时,我认为你停止使用最明显的选择。
来自http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13
的HTTP规范应用程序应该使用此字段 表示转移的长度 消息体,除非是这样 本节规则禁止的 4.4。
如果您知道长度,并且听起来就像您要的那样,请在Content-Length标题中指定并完成它,因为规范基本上是要求您这样做(假设您没有其他任何违反了上述规则) http://www.w3.org/Protocols/rfc2616/rfc2616-sec4.html#sec4.4)。
答案 5 :(得分:2)