HTTP协议详解与回顾

HTTP

HTTP(超文本传输协议)是一个基于请求与响应模式的、无状态的、应用层的协议,常基于TCP的连接方式,HTTP1.1版本中给出一种持续连接的机制,绝大多数的Web开发,都是构建在HTTP协议之上的Web应用。HTTP请求的有三次握手建立连接,四次挥手断开连接。最终都是为了进行可靠传输服务。这里不做过多说明,如有兴趣,请参阅《TCP/IP详解》三本神书。
HTTP协议的版本:HTTP/1.0、HTTP/1.1版本

HTTP/1.1版本

这个版本增加了持久连接,就是说之前版本的协议一次请求就是一次TCP连接,请求完成后这个连接就关闭掉了。众所周知TCP协议是可靠的,建立连接需要3次握手,断开连接需要4次挥手,并且TCP有流量控制和拥塞控制,有慢开始机制,刚建立连接时传输比较慢,这是比较耗费资源的。一个丰富的页面会有许多图片、表单和超链接。这样的话就会有多次的HTTP请求,所以在这个版本上默认不关闭TCP连接也不用声明Connection: keep-alive字段。如果确实要关闭可以指定Connection: close字段。还引入了管道机制,就是说在一个TCP连接里可以同时发送多个HTTP请求,而不必等待上一个请求响应成功再发送。还增加了PUT、PATCH、HEAD、 OPTIONS、DELETE等命令,丰富了客户端和服务端交互动作。还增加了Host字段。

HTTP协议的特点

HTTP协议是无状态的

就是说每次HTTP请求都是独立的,任何两个请求之间没有什么必然的联系。但是在实际应用当中并不是完全这样的,引入了Cookie和Session机制来关联请求。

多次HTTP请求

在客户端请求网页时多数情况下并不是一次请求就能成功的,服务端首先是响应HTML页面,然后浏览器收到响应之后发现HTML页面还引用了其他的资源,例如,CSS,JS文件,图片等等,还会自动发送HTTP请求这些需要的资源。现在的HTTP版本支持管道机制,可以同时请求和响应多个请求,大大提高了效率。

基于TCP协议

HTTP协议目的是规定客户端和服务端数据传输的格式和数据交互行为,并不负责数据传输的细节。底层是基于TCP实现的。现在使用的版本当中是默认持久连接的,也就是多次HTTP请求使用一个TCP连接。

代码

1
2
3
4
5
6
7
8
9
10
11
public class TcpSever {
public static void main(String[] args) throws Exception {
ServerSocket ss = new ServerSocket(10000);
Socket s = ss.accept();
InputStream in = s.getInputStream();
byte[] by = new byte[1024];
int len = in.read(by);
System.out.println(new String(by, 0, len));
}
}

写一个简单的HTML文件,带一个form表单。

请求头

get的请求方式

1
<form action="http://127.0.0.1:10000" method="get">


1
2
3
4
5
6
7
8
9
GET /?userName=jiujiu&pass=123&sex=nan&hobby=sports&country=CN
&province=GZ&area=GZ&btn1=%CC%E1%BD%BB%B1%ED%B5%A5 HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:10000
DNT: 1
Connection: Keep-Alive

Get方式的特点:传送的数据量受URL地址栏限制,传输的数据直接拼在URL地址后,以问号开始(?),多参数分隔以与符号开始(&)。直接传输中文会乱码,HTTP头字段只接受ASCII码值数据。jsp中可以通过URLEncoder.encode()转换成ASCII码值。

post的请求方式

1
<form action="http://127.0.0.1:10000" method="post">


1
2
3
4
5
6
7
8
9
10
11
12
13
POST / HTTP/1.1
Accept: text/html, application/xhtml+xml, */*
Accept-Language: zh-Hans-CN,zh-Hans;q=0.8,en-US;q=0.5,en;q=0.3
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64; Trident/7.0; rv:11.0) like Gecko
Accept-Encoding: gzip, deflate
Host: 127.0.0.1:10000
Content-Length: 105
DNT: 1
Connection: Keep-Alive
Cache-Control: no-cache
userName=hehe&pass=4321&sex=nan&hobby=sports&country=CN&province=GZ&area=GZ&btn1=%CC%E1%BD%BB%B1%ED%B5%A5

Post方式的特点:传送的数据量无限制。传输的数据是放在请求体中。

常用请求头说明

  • 请求头与请求体的分隔,是以一个空行隔开的。
  • 第一行为请求行,包含请求方式与HTTP协议版本号。
  • Accept: 浏览器所支持的数据类型。
  • Accept-Charset: 浏览器所支持的数据类型。
  • Accept-Encoding: 浏览器支持的压缩格式
  • Accept-Language: 浏览器支持的语言环境
  • Host: 想访问哪台主机
  • If-Modified-Since: 缓存数据的时间。浏览器为了提高性能,一般情况会缓存第一次的请求结果,在缓存数据时间内,会直接找本地缓存数据。
  • Referer: 客户机是从哪个页面来的。作用:服务器可以做判断,进行防盗链。
  • Connection: 请求完后是断开还是保持连接。

响应头

下图是一个IE插件,HttpWatch捕捉到的一次请求。左边是请求头,右边是响应头。

常用响应头说明

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
HTTP/1.1 200 OK
Server: bfe/1.0.8.18
Date: Wed, 05 Jul 2017 01:49:57 GMT
Content-Type: text/html; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Cache-Control: private
Cxy_all: baidu+63b9ff6074957f7dc4b1c7d31442fcfd
Expires: Wed, 05 Jul 2017 01:49:46 GMT
X-Powered-By: HPHP
X-UA-Compatible: IE=Edge,chrome=1
Strict-Transport-Security: max-age=172800
BDPAGETYPE: 1
BDQID: 0xfafa4d1200006790
BDUSERID: 0
Set-Cookie: BDSVRTM=0; path=/
Set-Cookie: BD_HOME=0; path=/
Set-Cookie: H_PS_PSSID=1425_21115_17001_23632_20929; path=/; domain=.baidu.com
Content-Encoding: gzip

第一行为状态行,状态码用于表示服务器对请求的处理结果。
Location: 跳转到哪里,通常是跟状态码302一起出现。
Server: 告诉浏览器,服务器型号
Content-Encoding: 告诉浏览器,数据的压缩格式
Content-Length: 告诉浏览器,回送数据的长度
Content-Type: 告诉浏览器,回送数据的类型
Content-Language: 语言环境
Refresh: 告诉浏览器,定时刷新
Content-Dispostion: 告诉浏览器以下载方式打开数据
Transfer-Encoding: 数据是以分块方式回送的
Expires: -1
Cache-Control: no-cache
Pragma: no-cache
后面三个都是控制浏览器不要缓存。

常见的状态码

100~199:表示成功接收请求,要求客户端继续提交下一次请求才能完成整个处理过程
200~299:表示成功接收请求并已完成整个处理过程,常用200(OK)
300~399:为完成请求,客户需进一步细化请求。例如,请求的资源已经移动一个新地址,常用302、304(未改动)和307(暂时重定向)
400~499:客户端的请求有错误,常用404(找不到资源)
500~599:服务器端出现错误,常用500(内部服务器错误)

响应体

响应头与响应体之间也是以一个空行分隔的。响应体的数据都是二进制数据,浏览器能解析。

关于HTTP的常见问题及解答

GET和POST的区别

  • 从字面意思和HTTP的规范来看,GET用于获取资源信息而POST是用来更新资源信息。
  • GET提交请求的数据实体会放在URL的后面,用?来分割,参数用&连接,举个栗子:/index.html?name=wang&login=1
  • GET提交的数据长度是有限制的,因为URL长度有限制,具体的长度限制视浏览器而定。而POST没有。
  • GET提交的数据不安全,因为参数都会暴露在URL上。

408 Request Timeout和504 Gateway Timeout的区别

408是说请求超时,就是建立连接之后再约定的时间内客户端没有发送请求到客户端到服务端。本质上原因在于客户端或者网络拥塞。504是网关超时,是说代理服务器把客户端请求转发到应用服务器后再约定的时间内没有收到应用服务器的响应。本质上原因在于服务端的响应过慢,也有可能是网络问题。

Cookie和Session的区别和联系

Cookie和Session都是为了保存客户端和服务端之间的交互状态,实现机制不同,各有优缺点。首先一个最大的区别就是Cookie是保存在客户端而Session就保存在服务端的。Cookie是客户端请求服务端时服务器会将一些信息以键值对的形式返回给客户端,保存在浏览器中,交互的时候可以加上这些Cookie值。用Cookie就可以方便的做一些缓存。Cookie的缺点是大小和数量都有限制;Cookie是存在客户端的可能被禁用、删除、篡改,是不安全的;Cookie如果很大,每次要请求都要带上,这样就影响了传输效率。Session是基于Cookie来实现的,不同的是Session本身存在于服务端,但是每次传输的时候不会传输数据,只是把代表一个客户端的唯一ID(通常是JSESSIONID)写在客户端的Cookie中,这样每次传输这个ID就可以了。Session的优势就是传输数据量小,比较安全。但是Session也有缺点,就是如果Session不做特殊的处理容易失效、过期、丢失或者Session过多导致服务器内存溢出,并且要实现一个稳定可用安全的分布式Session框架也是有一定复杂度的。在实际使用中就要结合Cookie和Session的优缺点针对不同的问题来设计解决方案。

谢谢你请我吃糖果

--------- 本文结束,感谢您的审阅 ---------
0%