网络协议分层
- 应用层
- http,ftp,websocket,smtp等
- 传输层
- tcp,udp
- 网络互联层
- ip
- 主机到网络层
- 以太网,wifi等
TCP的三次握手(建立连接)和四次挥手(关闭连接)
首先我们先理解几个概念
1. SYN: (同步序列编号,Synchronize Sequence Numbers)
2. ACK: (确认编号,Acknowledgement Number)
3. FIN: (结束标志,FINish)
三次握手过程
- 服务端处于LISTEN状态,等待客户端发出请求;
- 客户端发起一个和服务创建TCP链接的请求syn包,即SYN=1 seq=x,客户端进入SYN_SEND状态,等待服务器确认;
- 服务端接受到请求后,返回一个确认包ACK=1,SYN=1确认号是ack=x+1,seq=y;服务器进入SYN_RECV状态;
- 客户端收到服务器发送的确认包后,返回给服务端一个确认包ACK=1,确认号是ack=y+1,seq=x+1,客户端进入ESTABLISHED(已建立连接)状态
- 服务端这时接受到客户端的ACK信后,不再返回信息,也进入ESTABLISHED状态,后面进入数据通讯阶段
一个完整的三次握手也就是 请求—应答—再次确认
目的:确保可以提供可靠的连接服务。
一次握手: 建立不了连接,客户端发送请求后,服务端不回应,客户端是无法判断是否可以建立连接了
两次握手:服务器端不知道客户端发送的一个SYN是否已经是无效的了。
假设只有两次握手,那么有如下场景:
客户端A发送SYN,然后等待服务端B回应确认ACK,但这时网络不好,B没有收到;
A在一段时间后没收到回应ACK,就再发送一个请求SYN,把第一次发送的SYN作废,这次B顺利收到,返回ACK,A也收到,建立连接,可以开始通信;
这时A发送的第一个SYN终于到达了B,对于B来说这是一个新连接,然后B又为这个连接申请资源,返回ACK;
然而这个SYN现在是个无效的请求,A在收到ACK时候就不会理会这个请求(A是知道SYN已经是无效的了);
因为只有两次握手,那么B就不知道这个SYN已经是无效的了,B会一直为这个连接维持着资源,造成资源的浪费。
如果是有三次握手,那么B在收不到A的第三次握手的ACK确认后,一段时间后就会释放掉维持链接的资源。
四次挥手过程
数据传输完毕后,双方都可释放连接。最开始的时候,客户端和服务器都是处于ESTABLISHED状态,然后客户端主动关闭,服务器被动关闭。
1. 客户端进程发出连接释放报文FIN=1,seq=u;此时客户端进入FIN-WAIT-1(终止等待1)状态
2. 服务器收到连接释放报文,会给客户端发出确认报文ACK=1,确认序号ack=u+1,seq=v;服务端就进入了CLOSE-WAIT(关闭等待)状态
3. 客户端收到确认后,进入FIN-WAIT-2(终止等待2)状态;等待服务器发送连接释放报文(在这之前还需要接受服务器发送的最后的数据)。
4. 服务器将最后的数据发送完毕后,就向客户端发送连接释放报文,FIN=1,ack=u+1,seq=w,服务器就进入了LAST-ACK(最后确认)状态,等待客户端的确认。
5. 客户端收到服务端最终的释放请求后,发送确认报文ACk=1,ack=w+1,seq=u+1,进入了TIME-WAIT(时间等待)状态。注意此时TCP连接还没有释放,必须经过2∗∗MSL(最长报文段寿命)的时间后,当客户端撤销相应的TCB后,才进入CLOSED状态。
6. 服务器只要收到了客户端发出的确认,立即进入CLOSED状态
HTTP1.0、HTTP1.x、HTTP2
HTTP是建立在TCP协议之上,是应用层协议。
各个版本之间的主要区别是:
1. 长连接
HTTP 1.0需要使用keep-alive参数来告知服务器端要建立一个长连接,而HTTP1.1默认支持长连接。
HTTP是基于TCP/IP协议的,创建一个TCP连接是需要经过三次握手的,有一定的开销,如果每次通讯都要重新建立连接的话,对性能有影响。因此最好能维持一个长连接,可以用个长连接来发多个请求。
2. 节约带宽
HTTP 1.1支持只发送header信息(不带body),如 果服务器认为客户端有权限请求服务器,则返回100,否则返回401。客户端如果接受到100,才开始把请求body发送到服务器。
这样当服务器返回401的时候,客户端就可以不用发送请求body了,节约了带宽。
另外HTTP还支持传送内容的一部分。这样当客户端已经有一部分的资源后,只需要跟服务器请求另外的部分资源即可。这是支持文件断点续传的基础。
3. HOST域
现在可以web server例如tomat,设置虚拟站点是非常常见的,也即是说,web server上的多个虚拟站点可以共享同一个ip和端口。
HTTP1.0是没有host域的,HTTP1.1才支持这个参数。
4. 多路复用
HTTP2.0使用了多路复用的技术,做到同一个连接并发处理多个请求,而且并发请求的数量比HTTP1.1大了好几个数量级。
当然HTTP1.1也可以多建立几个TCP连接,来支持处理更多并发的请求,但是创建TCP连接本身也是有开销的。
TCP连接有一个预热和保护的过程,先检查数据是否传送成功,一旦成功过,则慢慢加大传输速度。因此对应瞬时并发的连接,服务器的响应就会变慢。所以最好能使用一个建立好的连接,并且这个连接可以支持瞬时并发的请求。
5. 数据压缩
HTTP1.1不支持header数据的压缩,HTTP2.0使用HPACK算法对header的数据进行压缩,这样数据体积小了,在网络上传输就会更快。
6. 服务器推送
意思是说,当我们对支持HTTP2.0的web server请求数据的时候,服务器会顺便把一些客户端需要的资源一起推送到客户端,免得客户端再次创建连接发送请求到服务器端获取。这种方式非常合适加载静态资源。
服务器端推送的这些资源其实存在客户端的某处地方,客户端直接从本地加载这些资源就可以了,不用走网络,速度自然是快很多的。
Socket通信
套接字,是一个对 TCP / IP协议进行封装 的编程调用接口(API)
Socket不是一种协议,而是一套API,属于传输层(主要解决数据如何在网络中传输,对TCP/IP的封装)
成对出现,一对套接字:
Socket ={(IP地址1:PORT端口号),(IP地址2:PORT端口号)}
https
HTTPS是在HTTP的基础上和ssl/tls证书结合起来的一种协议,保证了传输过程中的安全性,减少了被恶意劫持的可能.很好的解决了解决了http的三个缺点(被监听、被篡改、被伪装)
对称加密: 加密和解密时使用的是同一个秘钥
非对称加密、公钥私钥: 需要两个密钥来进行加密和解密,这两个 密钥分为公钥和私钥,他们是一对,公钥可以公开,私钥需要保密,公钥加密的数据私钥可以解密,私钥加密的数据公钥可以解密
证书签名请求csr: 包含申请者信息,如域名,有效期等,加密算法等
证书crt: 公钥+申请者与颁发者信息+签名
https请求的准备工作
- 服务端生成公私钥要server.key,server.pub
- 由server.pub生成证书签名请求server.csr,csr包含域名/申请者/公钥等信息
- 服务端将server.csr提供给CA机构,CA机构有自己的私钥ca.key和证书ca.crt;CA机构通过自己的ca.key对服务端提供server.csr进行加密签名,生成服务端证书server.crt;由公私钥的原理可知:CA机构的证书ca.crt可以对服务端证书server.crt进行解密
- server.crt提供给服务器
- 客户端内置CA机构的证书ca.crt,这样客户端就可通过ca.crt验证服务端的合法性
- 同理可生成客户端的证书client.crt,然后服务端通过ca.crt验证客户端的合法性
单向认证,双向认证
- 单向认证指的是只有一个对象校验对端的证书合法性。
通常都是client来校验服务器的合法性。那么client需要一个ca.crt,服务器需要server.crt,server.key - 双向认证指的是相互校验,服务器需要校验每个client,client也需要校验服务器。
server 需要 server.key 、server.crt 、ca.crt
client 需要 client.key 、client.crt 、ca.crt
https请求的过程(双向认证)
- 客户端发起链接请求(TCP的三次握手),建立连接
- 服务器将server.crt证书返回给客户端
- 客户端用内置的ca.crt验证server.crt,确保服务端的合法性;
- 如服务端合法,从server.crt中可获取服务端的公钥server.pub,然后客户端生成一个随机数密钥random_number,然后用服务端公钥S.Pub对其加密生成密文S.Pub(random_number),发送到服务端,同时发送客户端的证书client.crt到服务端
- 服务端通过ca.crt验证客户端证书client.crt的合法性
- 服务端收到客户端发送过来的加密随机数密钥S.Pub(random_number),用服务端的私钥S.Pri解密,获得客户端生成的随机数密钥random_number
- 之后客户端和服务端之间通信的内容,会通过随机数密钥random_number进行对称加密,此时由于random_number是服务端和客户端都知道的,所以他们之间的加密内容可以解密,最终获取明文
https是怎么确保安全的
https数据传输最终是对称加密过的
如果https请求被劫持,由于劫持者的证书无法通过验证,故连接会被终止
在一些开发中,经常有些人会忽略证书验证,这样的做法是风险非常大的。
劫持者就可以通过伪造证书,让客户端以为劫持者是服务端,让服务端以为劫持者是客户端,然后劫持者用自己的证书和私钥与客户端/服务端通信,从而监听篡改数据
大多数网站是不需要知道客户端的合法性的(比如百度,微博等),客户端只需知道我浏览的是正常网站,不是钓鱼网站即可,这样可以只做单向验证
但是对安全性要求高的网银,支付宝等,需要做双向验证(这些网站进入交易时会要求安装数字证书,其实就是为了双向验证,验证客户端的合法性),防止客户端被劫持,篡改客户端提交的数据(如客户端提供的的转账数据等)