如何通过关闭连接确定体长(RFC 2616 4.4.5)

时间:2015-05-12 21:45:17

标签: sockets http tcp rfc2616

我无法做到一件事。 RFC 2616 in 4.4.5表示Message Length可以确定" By the server closing the connection."。

这意味着服务器响应(例如返回一个大图像)的响应是有效的,它在标题中没有Content-Length,但客户端应该继续获取直到连接已关闭,然后假设已下载所有数据。

但客户如何确定连接是否被服务器故意关闭?服务器应用程序可能在发送数据的过程中崩溃,服务器的操作系统很可能会发送FIN数据包以正常关闭与客户端的TCP连接。

1 个答案:

答案 0 :(得分:3)

You are absolutely right, that mechanism is totally unreliable. This is covered in RFC 7230:

Since there is no way to distinguish a successfully completed, close-delimited message from a partially received message interrupted by network failure, a server SHOULD generate encoding or length-delimited messages whenever possible. The close-delimiting feature exists primarily for backwards compatibility with HTTP/1.0.

Fortunately most of HTTP traffic today are HTTP/1.1, with Content-Length or "Transfer-Encoding" to explicitly define the end of message.

The lesson is that, a message must have it own way of termination; we cannot repurpose the underlying transport layer's EOF as the message's EOF.

On that note, a (well-formed) require 'vendor/autoload.php'; use Facebook\FacebookSession; use Facebook\FacebookRequest; use Facebook\GraphUser; use Facebook\FacebookRequestException; use Facebook\FacebookRedirectLoginHelper; FacebookSession::setDefaultApplication(123456,'a1b2c3d4e5'); $helper = new FacebookRedirectLoginHelper('http://domain.com/login.php'); try { # success $session = $helper->getSessionFromRedirect(); } catch(FacebookRequestException $ex) { # when Facebook returns an error } catch(\Exception $ex) { # when validation fails or other local issues } if($session) { # do something with user data $me = (new FacebookRequest($session, 'GET', '/me'))->execute()->getGraphObject(GraphUser::className()); # redirect to user profile page header('Location: http://domain.com/profile.php'); exit(); } else { # $session is always NULL with this code :( } document, or a html, .gif etc, does define its own termination; we will know if we received an incomplete document. Therefore it is not so much of a problem to transmit it over HTTP/1.0 without Content-Length.

However, for plain text document, .avi, javascript etc. EOF is used to marked the end of the document, therefore it's problematic over HTTP/1.0.