1 HTTP消息:
Generic-message = start-line*(message-header CRLF) CRLF [message-body]
Start-line=Request-Line|Status-Line
服务器【应该】忽略在希望收到Request-Line地方的空行,换句话,如果服务器在读取协议流的初始消息且收到CRLF打头,则它应该忽略CRLF,已知有问题的HTTP/1.0客户端实现生成额外的CRLF在POST请求之后。重新声明,BNF明确禁止HTTP/1.1客户端一问我的CRLF引导或结束请求
1.1 Message-header
1.1.1.1 收到不同field-name头部域的顺序没有意义,然而好的实践是,首先发送general-header , 接着是 request-header或者response-header,然后是entity-header域
1.1.1.2 通过追加每个后序field-value到第一个,之间用逗号分隔开,因此收到相同field-name头部域的顺序对应组合field-value的解析是有意义的,代理【禁止】在转发消息时改变这些field-value的顺序
1.2 Message-body (如果存在)用于携带与请求或响应相关联的entity-body,message-body只有在应用了transfer-encoding时,通过Transfer-Encoding 头部域指出,与entity-body不同
Message-body = entity-body | <按每个Transfer-Encoding编码的entity-body>
*当允许消息有message-body时的规则对应请求和响应而言是不同的
1.1.1.1 请求中存在message-body的信号有在请求的message-header中引入Content-length或者Transfer-Encoding来指示。如果请求方法规定不允许在请求中发送entity-body是,【禁止】在请求中包括message-body,服务器【应该】读取和转发任何请求上的message-body,如果请求没有包括entity-body的已定义语句,在处理请求时【应该】忽略message-body
1.1.1.2 响应消息是否包括message-body既取决于请求方法,也取决于响应状态码,对应HEAD请求方法的所有请求【禁止】包括message-body,即使存在entity-header域可能使接收方确信其中包括message-body,所有1xx(信息性),204(No content),,和304(Not-modified) 响应【禁止】包括message-body,所有其他响应确实包括message-body,即使其长度【可以】是0
1.2 消息长度
1.2.1 【禁止】包括message-body的任何响应(如1xx,204和304响应,及对HEAD请求的任何响应)始终在头部域的首个空行后终止,而不管消息中的entity-header域
1.2.2 如果存在Transfer-Encoding头部域,且其值不是”identity”,这时transfer-length由“chunked”transfer-encoding定义,除非消息由连接关闭终止
1.2.3 如存在Content-length头部域,则它的OCTET十进制既表示entity-length,又表示content-length,如果这两个长度不同时,【禁止】发送Content-length头部域,如果收到的消息既有Transfer-Encoding头部域,又有Content-length头部域,则【必须】忽略后者
1.2.4 如果消息使用”multipart/byteranges“媒体类型,且没有另外指定transfer-length,则该自定界的媒体类型定义transfer-length,除非发送方知道接收方能够解释它,否则【禁止】使用该媒体类型。1.1客户端请求中存在多个byte-range规范符的Range头部暗示该客户端能解释multipart/byteranges响应,1.0代理啃个不理解multipart/byteranges,可以转发Range头部,在这种情况下,服务器【必须】使用本节中1,3,5项定义的方法来定界消息
1.2.5 通过服务器关闭连接(不能使用关闭连接来指出请求主体的结束,由于这将引起服务器不可能回送响应)
为了与HTTP/1.0应用程序兼容,包含message-body的HTTP/1.1请求【必须】包括有效的Content-length头部域,除非已知服务器与HTTP/1.1兼容,如果请求中包含message-body但没有Content-length,则服务器【应该】在不能判断消息长度时用400(Bad Request)响应,或者在希望坚持接受有效content-length时用411(Length Required)响应
收到实体的所有HTTP/1.1应用程序【必须】接受”chunked”的transfer-encoding,允许在将来不能判断长度时该机制用于消息。【禁止】消息既包括Content-length头部域,又包括非identity的transfer-encoding,如果消息确实包括非identity的transfer-encoding,则【必须】忽略content-length,当在运行message-body的消息给出content-length时,它的field-value【必须】精确匹配message-body的OCTET数量,HTTP/1.1用户代理【必须】提醒用户接收并检测到无效长度。
2 General-header
2.1 Cache-Control
2.2 Connection
2.3 Date
2.4 Pragma
2.5 Trailer
2.6 Transfer-Encoding
2.7 Upgrade
2.8 Via
2.9 Warning
3 Socket模拟HTTP协议,读取header,根据content-length,读取http body
public static byte[] ReceiveData(Socket socket)
{
StringBuilder header=new StringBuilder();
string headertext="";
while(true)
{
byte[] data=new byte[1];
//接收一个字节
int rece=socket.Receive(data,1,SocketFlags.None);
//转换为char
char c=(char)data[0];
header.Append(c);
//检查是否到了包头末尾,如果到了包头末尾,那么停止
//读取
if(header.ToString().IndexOf("/r/n/r/n")>0)
{
string content="CONTENT-LENGTH:";
int start=header.ToString().ToUpper().IndexOf(content);
headertext=header.ToString().Substring(start+content.Length);
int end=headertext.IndexOf("/r/n");
headertext=headertext.Substring(0,end); //包体长度
break;
}
}
//
byte[] ds=ReceiveData(socket,Convert.ToInt16(headertext));
return ds;
}