1、概述
(1)HTTP是应用层协议,是从Web服务器传输超文本到本地浏览器的传送协议,端口号为80。
(2)默认情况下HTTP使用TCP,但是也可以基于以后存在的其他可靠传输协议。由于UDP无法提供可靠传输,所以不会使用UDP。
(3)1990年提出,现在广泛使用的版本是HTTP1.0和HTTP1.1。
(4)无连接/短连接:无连接的含义是限制每次连接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开连接。采用这种方式可以节省传输时间。HTTP1.0中通过Connection:keep-Alive,可以使用长连接;HTTP1.1中默认是长连接的。
(5)无状态:是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。
(6)支持客户/服务器模式。
(7)简单快速:客户向服务器请求服务时,只需传送请求方法和路径。请求方法常用的有GET、PUT、POST等。每种方法规定了客户与服务器联系的类型不同。由于HTTP协议简单,使得HTTP服务器的程序规模小,因而通信速度很快。
(8)灵活:HTTP允许传输任意类型的数据对象。正在传输的类型由Content-Type加以标记。
2、 HTTP如何建立连接
HTTP协议是建立在请求/响应模型上的。首先由客户建立一条与服务器的TCP链接,并发送一个请求到服务器,请求中包含请求方法、URI、协议版本以及相关的MIME样式的消息。服务器响应一个状态行,包含消息的协议版本、一个成功和失败码以及相关的MIME式样的消息。
HTTP/1.0为每一次HTTP的请求/响应建立一条新的TCP链接,因此一个包含HTML内容和图片的页面将需要建立多次的短期的TCP链接。一次TCP链接的建立将需要3次握手。
另外,为了获得适当的传输速度,则需要TCP花费额外的回路链接时间(RTT)。每一次链接的建立需要这种经常性的开销,而其并不带有实际有用的数据,只是保证链接的可靠性,因此HTTP/1.1提出了可持续链接的实现方法。HTTP/1.1将只建立一次TCP的链接而重复地使用它传输一系列的请求/响应消息,因此减少了链接建立的次数和经常性的链接开销。
3、常用请求方式:get和post
(1)GET
使用时机:直接在浏览器地址栏输入访问地址所发送的请求或提交表单发送请求时,该表单对应的form元素没有设置method属性,或设置method属性为get,这几种请求都是get方式的请求。
数据位置:get方式的请求会将请求参数的名和值转换成字符串,并附加在原URL之后,因此可以在地址栏中看到请求参数名和值。
数据量大小:get请求传送的数据量较小,一般不大于2KB。
用途:get通常用于向服务器索取数据
(2)POST
使用时机:通常使用提交表单的方式发送,且表单设置form元素的method属性为post。
数据位置:post方式发送的请求参数以及对应的值放在body中传输,用户在地址栏看不到请求参数值,安全性较高。
数据量大小:post传送的数据量较大,一般认为没有限制,往往取决于服务器的限制。
用途:post通常用于向数据库提交数据
(3)关于HTTP协议与HTML标准:按照HTTP协议,put/get/post/delete分别对应CRUD操作,但是并没有做具体的技术限制。HTML标准是HTTP协议的一个应用(可以说是最广泛的应用),在HTML中对get与post做了一些限制,如上所述。因此如果只是问get与post的区别,那么在http协议语境下,可以说没有什么区别。【作为前端人员和后台人员,应该尽量按照http协议的建议来,以避免不一致,即get取数据,post传数据】
(4)数据量大小:实际上HTTP协议对get/post的url长度、head和body都没有做长度的限制;对url长度的限制主要是由于浏览器、服务器为了减轻负担。
(5)安全:如果对url参数进行编码,则get与post的安全性是相同的,即小白用户都看不到,技术人员都能看到(对url参数进行解码,或查看body中的数据)。安全还有另外一种理解,即get不会修改网站内容,而post会(根据http协议的建议),从这个角度来看,get是安全的(即没有副作用),post是不安全的。还有一点需要注意,资源不能发post请求,即不能使用img、embed、CSS的url()以及样式表引用、脚本引用、框架页引用等对一个URL发起POST请求。
4、请求消息格式
(0)举例
GET / HTTP/1.1
HOST:www.baidu.com
Connection:keep-Alive
[空行]
实体内容
(1)请求行+通用信息头/请求头/实体头+实体内容;以上每行之间需要"\r\n"(又叫CRLF),实体内容前面需要两个,实体内容之后不需要。
(2)请求行:方法符号+空格+URI+空格+协议版本
方法符号有:GET/POST/HEAD/PUT/DELETE/TRACE/CONNECT/OPTIONS
URI:可以不包含IP和端口(因为HOST中会指定),但必须指明资源路径。
协议版本:HTTP/1.1或者HTTP/1.0
(3)常见的请求头
HOST:客户端指定想访问的http服务器的域名/IP和端口号;1.0中可以缺省此项,1.1中可以为空值,但是不能缺省;响应头中没有HOST选项;HOST值可以由程序自定义;I:可以缺省,我猜测是因为TCP中可能包含这些信息。
User-Agent:浏览器类型
Accept:浏览器可以接受的MIME类型(*/*是可以接受所有的MIME类型)
Connection:表示是否需要持久链接;若是”Keep-Alive“,或者请求使用的是HTTP/1.1,会持久链接。
Range:bytes=0-100,300-400:可以请求实体的一个或多个子范围;没有这个字段,请求整个实体;形式还可以是bytes=20-或者bytes=-200。
Authorization:认证信息,值一般是将用户名和密码拼接成"user:password"的形式,然后进行Base64加密,称为Basic认证【如果没有这个信息,或者信息错误,服务器会返回401:Unauthorized】
Cookie
Cache-control:网页缓存,可参考http://my.oschina.net/mickelfeng/blog/103180?fromerr=Y7q2cHSs
content-type:内容类型,request的内容类型而不是response的内容类型(当然,如果response中指定,则是response的内容类型)。一般格式为type/subtype;parameter,type主要包括text/application/multipart/video/audio/image/message,parameter一般用来指定text/plain和text/html的编码格式。【以下类型不区分request和response】
text:文本类型,如plain、html、css等
application:应用程序数据或二进制数据,如zip、pdf、x-www-form-urlencoded、json、xml等
multipart/form-data : 需要在表单中进行文件上传时,就需要使用该格式
message:用于包装一个E-mail消息
【对于form的说明:当使用get时,form中的内容会加入到url后面的QueryString中;当使用post时,form中的内容会加入到body中。如果此时没有type=file的控件,用application/x-www-form-urlencoded即可;否则需要使用multipart/form-data】【该描述涉及了get与post,个人猜测其实是HTML标准规定的内容,而不是HTTP协议规定的内容】
application/octet-stream:代表任意的二进制数据传输;如果response没有指定内容类型,而是直接向下面这样写数据,则内容类型为octet-stream.
PrintWriter writer = response.getWriter(); writer.print("hello world"); writer.flush(); writer.close();
5、响应消息格式
(1)状态行+消息报头+空行+实体内容;空行规则与请求消息类似,消息报头与请求头格式类似。
(2)状态行:HTTP-Version+Status-Code+Reason-Phrase+CRLF(即\r\n)
(3)HTTP-Version:HTTP/1.1
(4)Status-Code:状态码由三位数字组成,第一位定义了响应类别
1**:请求已接收,正在处理
2**:成功,请求已经接收、理解、接受
3**:重定向,要完成请求,必须进行进一步操作
4**:客户端错误,请求有语法错误,或请求无法实现
5**:服务器端错误,服务器未能实现合法请求
(5)常见状态码
200:OK
400:Bad Request
401:Unauthorized
403:Forbidden
404:Not Found
500:内部服务器错误
502:Bad Gateway
(6)头部
content-disposition:当服务器向浏览器发送文件时,如果不希望浏览器直接打开,而是下载文件,则需要指定该头,如下所示,其中downloadFileName是浏览器提示给用户的文件名。关于文件下载,请搜索《下载文件》。
response.setHeader("content-disposition","attachment; filename=" + downloadFileName);
6、实例
get、post与响应
GET /books/?sex=man&name=Professional HTTP/1.1 Host: www.wrox.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 Connection: Keep-Alive
POST / HTTP/1.1 Host: www.wrox.com User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.7.6) Gecko/20050225 Firefox/1.0.1 Content-Type: application/x-www-form-urlencoded Content-Length: 40 Connection: Keep-Alive (----此处空一行----) name=Professional%20Ajax&publisher=Wiley
HTTP/1.1 200 OK Date: Sat, 31 Dec 2005 23:59:59 GMT Content-Type: text/html;charset=ISO-8859-1 Content-Length: 122 <html> <head> <title>Wrox Homepage</title> </head> <body> <!-- body goes here --> </body> </html>
完整的get与响应
GET /DEMOWebServices2.8/Service.asmx/CancelOrder?UserID=string&PWD=string&OrderConfirmation=string HTTP/1.1 Host: api.efxnow.com HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <objPlaceOrderResponse xmlns="https://api.efxnow.com/webservices2.3"> <Success>boolean</Success> <ErrorDescription>string</ErrorDescription> <ErrorNumber>int</ErrorNumber> <CustomerOrderReference>long</CustomerOrderReference> <OrderConfirmation>string</OrderConfirmation> <CustomerDealRef>string</CustomerDealRef> </objPlaceOrderResponse>
完整的post与响应
POST /DEMOWebServices2.8/Service.asmx/CancelOrder HTTP/1.1 Host: api.efxnow.com Content-Type: application/x-www-form-urlencoded Content-Length: length UserID=string&PWD=string&OrderConfirmation=string HTTP/1.1 200 OK Content-Type: text/xml; charset=utf-8 Content-Length: length <?xml version="1.0" encoding="utf-8"?> <objPlaceOrderResponse xmlns="https://api.efxnow.com/webservices2.3"> <Success>boolean</Success> <ErrorDescription>string</ErrorDescription> <ErrorNumber>int</ErrorNumber> <CustomerOrderReference>long</CustomerOrderReference> <OrderConfirmation>string</OrderConfirmation> <CustomerDealRef>string</CustomerDealRef> </objPlaceOrderResponse>
7、Keep-alive
没有keep-alive:每个http请求都要求打开一个tpc socket连接,并且使用一次之后就断开这个tcp连接。
使用keep-alive:在一次TCP连接中可以持续发送多份数据而不会断开连接。通过使用keep-alive机制,可以减少tcp连接建立次数,也意味着可以减少TIME_WAIT状态连接,以此提高性能和提高httpd服务器的吞吐率(更少的tcp连接意味着更少的系统内核调用)。
弊端:长时间的tcp连接容易导致系统资源无效占用。配置不当的keep-alive,有时比重复利用连接带来的损失还更大。
措施:正确地设置keep-alive timeout时间。这个keepalive_timout时间值意味着:一个http产生的tcp连接在传送完最后一个响应后,还需要hold住keepalive_timeout秒后,才开始关闭这个连接。