我之所以添加另一个答案,主要是因为我的声望不够,在mgiuca的评论下无法发表评论。我知道这个问题有点老了,但还没有明确的答案。
正如提到的那样,需要考虑的主要问题是,您的服务器与不可控制的其他人进行交互,这意味着您无法知道他们将会发送什么,必须准备好处理通过该门传送的任何内容。在考虑这一点时,坚持标准和常规做法可能是最好的选择。
如果客户端发送了“Content-Length”头,则服务器必须解析它并使用它来确定请求的结束。如果没有这样的头文件,但存在“Transfer-Encoding: chunked”头文件,则服务器必须能够解析分块请求(link 参见mgiuca的答案)。最后,如果两者都不存在,则“连接的结束”表示请求的结束。
我认为你忽略了一个事实,即客户端可以结束连接并仍然从服务器获得响应。我的意思是,“结束连接”是什么意思?请记住,HTTP是一种应用层协议,通常通过TCP传输。探索TCP的功能(特别是其
connection termination协议)会揭示一些有趣的信息:
- 要主动结束连接,客户端发送带有FIN标志的数据包,这是四次握手的一部分。连接仍被视为打开状态,因为终止协议尚未完成。
- 服务器接收此数据包并通知客户端(ACK数据包)。服务器现在知道客户端不会再传输数据了。
- 客户端进入FIN_WAIT2状态,等待来自服务器的带有FIN标志的数据包以正确关闭连接。
但事实上,客户端已经通知要结束连接了,服务器也知道这一点,但是在客户端仍然保持连接打开(因为他还没有收到
FIN数据包),服务器现在回复请求并正常关闭连接。值得注意的是,客户端将使用额外的
RST标志确认每个服务器数据包,并告诉服务器他仍然期望
FIN来关闭连接。
当服务器完成操作后(在我们的小例子中,发送HTTP响应后),它会在自己的一侧关闭连接,发送FIN数据包。当客户端接收到它时,他会关闭自己的一侧,并用ACK通知服务器。
在此补充一点,我不知道您编程时所处的上下文,但大多数情况下,您最终会在套接字上调用
shutdown()。
POSIX的shutdown(以及
Windows至少)将要关闭的连接接口作为函数参数。这些规范明确指出,您可以仅关闭发送方部分(这正是客户端将要执行的操作),从而禁用数据发送,同时允许客户端接收更多数据。
TCP连接的进一步细节超出了本问题的范围,但我建议您阅读相关资料,以便更好地理解使用它的更高层协议。