当前位置:首页 > 服务器 > 正文

HTTP1.1请求返回状态码为100 Continue的分析说明和解决方法

使用HTTP/1.1协议的curl,发送一个请求,在post数据量超过1K的时候,接口会返回:

HTTP/1.1 100 Continue

HTTP/1.1 200 OK
Date: Sat, 07 Dec 2013 10:09:11 GMT
Server: Apache/2.2.24 (Unix) PHP/5.3.25
X-Powered-By: PHP/5.3.25
Content-Length: 43
Content-Type: text/html

从表面上看,100 Continue表明请求一次没发送完,需要继续发送;搜索后看到现在新浪微博PHP架构师的一片博文,介绍了100的信息;详见在使用curl做POST的时候, 当要POST的数据大于1024字节的时候, curl并不会直接就发起POST请求, 而是会分为俩步,;

流程如下:
1. 发送一个请求, 包含一个Expect:100-continue, 询问Server使用愿意接受数据
2. 接收到Server返回的100-continue应答以后, 才把数据POST给Server

使用libcurl的时候会碰到这样的问题;
在w3c的官网介绍看到如下一段话:

8.2.3 Use of the 100 (Continue) Status
The purpose of the 100 (Continue) status (see section 10.1.1) is to allow a client that is sending a request message with a request body to determine if the origin server is willing to accept the request (based on the request headers) before the client sends the request body. In some cases, it might either be inappropriate or highly inefficient for the client to send the body if the server will reject the message without looking at the body.
Requirements for HTTP/1.1 clients:
– If a client will wait for a 100 (Continue) response before
sending the request body, it MUST send an Expect request-header
field (section 14.20) with the “100-continue” expectation.
– A client MUST NOT send an Expect request-header field (section
14.20) with the “100-continue” expectation if it does not intend
to send a request body.

简单翻译一下:
使用100(不中断,继续)状态码的目的是为了在客户端发出请求体之前,让服务器根据客户端发出的请求信息(根据请求的头信息)来决定是否愿意接受来自客户端的包含了请求内容的请求;在某些情况下,在有些情况下,如果服务器拒绝查看消息主体,这时客户端发送消息主体是不合适的或会降低效率

对HTTP/1.1客户端的要求:
-如果客户端在发送请求体之前,想等待服务器返回100状态码,那么客户端必须要发送一个Expect请求头信息,即:”100-continue”请求头信息;

-如果一个客户端不打算发送请求体的时候,一定不要使用“100-continue”发送Expect的请求头信息;

10.1.1 100 Continue
The client SHOULD continue with its request. This interim response is used to inform the client that the initial part of the request has been received and has not yet been rejected by the server. The client SHOULD continue by sending the remainder of the request or, if the request has already been completed, ignore this response. The server MUST send a final response after the request has been completed. See section 8.2.3 for detailed discussion of the use and handling of this status code.
简单而言,100 Continue就是告诉客户端,请求的开始部分已经被接受,而且没有被拒绝,请客户端继续发送余下的请求;如果请求完成,忽略响应;在请求结束后,服务器必须要发送一个最终响应;
当然解决的方法也很简单,就是强制让客户端不要发送Expect,
curl_setopt($ch, CURLOPT_HTTPHEADER, array(‘Expect:’)); //这句话的意思是在请求的头信息中,强制清空Expect,这样服务器也就不会返回100 Continue,这样在curl中会增加请求延时的概率;
// Disable Expect: header (lighttpd does not support it)

经过测试,增加这一条头信息,的确是搞定了100响应头信息的问题;
为了进一步测试,我们使用了tcpdump所有的头信息:
tcpdump -ieth1 -s0 host 10.12.194.23 and port 80 -w/data/x.pcap
然后使用Wireshark查看相应的pcap文件,对比前后两处的请求,的确很明显的出现了100信息;
如下图:

MSS

200 success

这里可以看到整个请求的过程,比如TCP的3次握手,只有200返回的时候,在server返回【ACK】之后,直接发送了整个post请求,在有100的时候,这里找到了TCP segment of a reassembled PDU,这个是在
Wireshark独特出现的请求信息,参考了http://blog.csdn.net/rossini23/article/details/5424850,其中谈到了发现“TCP segment of a reassembled PDU”指TCP层收到上层大块报文后分解成段后发出去,用sniffer打开同样的trace 发现里面提示“Continuation of missing frame”和”Continuation of frame xx”;

MTU: Maxitum Transmission Unit 最大传输单元(在前端性能优化中,公司有前端优化高手就谈到过MTU,包括cookie在内,不要超过MTU,这样可以减少发包的次数)

备注:MSS: Maxitum Segment Size 最大分段大小(这个是新接触的概念),说明:
MSS最大传输大小的缩写,是TCP协议里面的一个概念。
MSS 就是TCP数据包每次能够传输的最大数据分段。为了达到最佳的传输效能TCP协议在建立连接的时候通常要协商双方的MSS值,这个值TCP协议在实现的时候往往用MTU值代替(需要减去IP数据包包头的大小20Bytes和TCP数据段的包头20Bytes)所以往往MSS为1460。通讯双方会根据双方提供的MSS值得最小值确定为这次连接的最大MSS值。

100 error

这里我产生了一定的疑问,这里MSS和MTU,两者之间到底关系如何?
博文做了如下解释:
如 果我们在中间路由器上把每次TCP连接的最大MSS进行调整这样使得通过PPPoE链路的最大MSS值加上数据包头包尾不会超过PPPoE的MTU大小:1492这样就不会造成无法通讯的问题.所以上面的问题可以通过iptcp adjust-mss 1452来解决。

这样我们可以理解为核心还是MTU,因为它是在数据链路层协议相关;

博文中介绍的1460Bytes和软件中列举的16396Bytes还是有很大的差距,可能是我理解有错误?

1 条评论

  1. 沙发2014-06-10 下午10:07回复
    现金玩棋牌游戏

    367920 671276Where else may just anyone get that kind of information in such a perfect way of writing? 257095

发表评论