1.HTTP
HTTP是超文本传输协议,英文写作HyperText Transfer Protocol,它是构建在TCP协议之上的。
在http的两端分别是客户端和服务器,这就是经典的B/S模式。另外,这里的B,就是浏览器的意思,浏览器成为了http的代理,用户的行为将会通过浏览器转化为http请求报文,发送给服务器,服务器也就是S,会处理请求,然后发送响应报文给代理,也就是浏览器,浏览器解析响应报文后,将用户界面展示给用户。这里我们看到,基于http或者https的B/S模式中国,浏览器只负责发送报文、接收报文、解析报文、展示界面,服务器负责处理http请求和发送http响应。
TCP全称为传输控制协议,在OSI模型上属于传输层协议。
七层协议示意图如下:
TCP是面向连接的协议,其显著特征是在传输之前需要3次握手形成会话。
只有会话形成后,服务器端和客户端才能相互发送数据。在创建会话的过程中,服务器端和客户端分别提供一个套接字,
这两个套接字共同形成一个连接。服务器端和客户端则通过套接字实现两者之间连接的操作。
http网络通信的所有报文信息如下,报文分为四部分。
$ curl -v http://127.0.0.1:1337
//第一部分:是经典的TCP三次握手,这样就建立了连接
* About to connect() to 127.0.0.1 port 1337 (#0)
* Trying 127.0.0.1...
* connected
* Connected to 127.0.0.1 (127.0.0.1) port 1337 (#0)
//第二部分:在完成握手之后,客户端向服务器端发送请求报文。
> GET / HTTP/1.1
> User-Agent: curl/7.24.0 (x86_64-apple-darwin12.0) libcurl/7.24.0 OpenSSL/0.9.8r zlib/1.2.5
> Host: 127.0.0.1:1337
> Accept: */*
>
//第三部分:服务器端完成处理后,向客户端发送的响应内容,包括响应头和响应体。
< HTTP/1.1 200 OK
< Content-Type: text/plain
< Date: Sat, 06 Apr 2013 08:01:44 GMT
< Connection: keep-alive
< Transfer-Encoding: chunked
<
Hello World
第四部分:结束会话的信息
* Connection #0 to host 127.0.0.1 left intact
* Closing connection #0
注意:报文的内容主要是两部分,报文头和报文体,上一个例子中,使用的是get请求,报文头的部分是上边报文信息中>和<的部分。在响应报文中,有一个报文体,是Hello World。
2.WebSocket
使用websocket的话,网页客户端只需一个TCP链接即可完成双向通信,在服务端与客户端频繁通信时,无须频繁断开连接和重发请求。连接可以得到高效应用。
特点如下:
(1)建立在 TCP 协议之上,服务器端的实现比较容易。
(2)与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
(3)数据格式比较轻量,性能开销小,通信高效。
(4)可以发送文本,也可以发送二进制数据。
(5)没有同源限制,客户端可以与任意服务器通信。
(6)协议标识符是ws
(如果加密,则为wss
),服务器网址就是 URL。
websocket与HTTP有如下好处:
- 客户端与服务器只建立一个tcp连接,可以使用更少的连接
- websocket服务器端可以推送数据到客户端,这远比HTTP请求响应模式更灵活,更高效。
- 有更轻量级的协议头,减少数据~~~~传送量
websocket分为握手和数据传输两部分,其中握手使用了http进行。
1)WebSocket握手
客户端建立连接是,通过HTTP发起请求报文。如下所示:
GET /chat HTTP/1.1
Host: server.example.com
//请求服务端升级协议为WebSocket
Upgrade: websocket
Connection: Upgrade
//用于安全校验
Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
//指定子协议和版本号
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
服务器端在处理完请求后,响应如下报文:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
Sec-WebSocket-Protocol: chat
这段报文将告诉客户端,正在更换协议,更新为应用层协议websocket,并在当前的套接字上应用新的协议。
剩余的字段分别表示服务器端基于Sec-WebSocket-Key生成的字符串和选中的子协议。客户端将会校验Sec-WebSocket-Accept的值,如果成功,将开始接下来的数据传输。
2)WebSocket数据传输
在顺利握手后,当前连接将不再进行http交互,而是开始websocket的数据帧协议,实现客户端与服务器的数据交换。
协议升级的过程如下:
当客户端调用send()发送数据时,服务器端触发onmessage(),当服务器端调用send()发送数据时,客户端的onmessage()触发,当我们调用send()发送一条数据时,协议可能将这个数据封装为一帧或多帧数据,然后逐帧发送。
为了安全考虑,客户端需要发送的数据帧进行掩码处理,服务器一旦收到无掩码帧,比如中间拦截破坏,连接将会关闭。服务器发送到客户端的数据帧无需做掩码,如果客户端收到了带掩码的数据帧,连接也将关闭。
传送的帧类型分为两类:数据帧(data frame)和控制帧(Control frame)。数据帧可以携带文本数据或者二进制数据;控制帧包含关闭帧(Close frame)和Ping/Pong帧。
在websocket中的数据帧的定义,每8位为一列,也就是一个字节,其中每一位都有它的意义:
- fin,如果这一帧是最后一帧,这个fin为为1,其余情况为0.
- rsv1、rsv2、rsv3,都是一位长,用于标识扩展,当有已协商的扩展时,这些值可能为1,其余情况为0。
- opcode,4位长,可以用来表示0~15的值,用于解释当前数据帧,0表示附加数据帧,1表示文本数据帧,2表示二进制数据帧,8表示发送一个连接关闭的数据帧,9表示ping数据帧,10表示pong数据帧,其余值暂时没有定义。ping数据帧和pong数据帧用于心跳检测,当一端发送一个ping数据帧时,另一端必须发送pong数据帧作为回应,告知对方这一端仍然处于响应状态。
Ping/Pong帧: Ping帧和Pong帧用于连接的保活(keepalive)或者诊断对端是否在线。这两种帧的发送和接收不对WEB应用公开接口,由实现WebSocket协议的底层应用(例如浏览器)来实现它。
- masked,表示是否进行掩码处理,1位长度,客户端发送给服务器时为1,服务器发送回客户端时为0.
- payload length:一个7、7+16或7+64位长的数据为,标识数据的长度,如果值在0~125之间那么该值就是数据的真实长度,如果是126,则后面16位的值是数据的真实长度,如果是127,则后面64位的值是数据的真实长度。
- making key,当masked为1时,这里是一个32位长的数据位,用于解密数据。
- payload data,我们的目标数据,位数为8的倍数。
客户端发送消息时,需要构造一个或多个数据帧协议报文,例如我们发送一个hello world,这个比较短,不存在分割多个数据帧的情况,并且以文本方式发送,他的payload length长度为96(12字节*8位/字节),二进制表示为110000。所以报文应该是:
fin(1) + res(000) + opcode(0001) + masked(1) + payload length(1100000) + masking key(32位) + payload
data(hello world!加密后的ܾ二进制)
服务器回复的是yakexi,这个无需掩码,形式如下:
fin(1) + res(000) + opcode(0001) + masked(0) + payload length(1100000) + payload data(yakexi的ܾ二进制)
连接关闭
任何一端发送关闭帧给对方,即可关闭连接。关闭连接时通常都带有关闭连接的状态码(status code)。常见状态码的含义如下:
- 1000 连接正常关闭
- 1001 端点离线,例如服务器down,或者浏览器已经离开此页面
- 1002 端点因为协议错误而中断连接
- 1003 端点因为受到不能接受的数据类型而中断连接
- 1004 保留
- 1005 保留, 用于提示应用未收到连接关闭的状态码
- 1006 端点异常关闭
- 1007 端点收到的数据帧类型不一致而导致连接关闭
- 1008 数据违例而关闭连接
- 1009 收到的消息数据太大而关闭连接
- 1010 客户端因为服务器未协商扩展而关闭
- 1011 服务器因为遭遇异常而关闭连接
- 1015 TLS握手失败关闭连接
参考链接:
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。