TCP/IP
简单网络模型
-
信息在网络上传输需要经过一些列的编码,封装和解码,获取信息,一般要经过七层传输,就是大家熟知的网络七层模型。此篇重点不是七层模型所以这里摘取跟此次讨论话题密切关联的两层应用层、传输层

-
应用层: 常用的HTTP,FTP等协议来对信息进行编码和解码。大家最熟悉的HTTP通过文本协议,一种协议的载体(画外音:通过\r\n来对流进行拆分,拆包技术一种,还有根据长度来拆包等),来保证用户接收到信息正确传递,解决拆包粘包问题。常用的应用层协议载体还有二进制,XML等等,比如
Protobuf,Dubbo采用二进制协议,二进制协议相对效率较高,我个人认为,所谓的应用层协议:主要是对信息编码和解码完成信息传输,而不同的载体存在效率上存在差异。 -
传输层: 通过对上面应用层数据的进一步的封装,屏蔽了与网络层进行交互的细节,提供端到端的数据传输服务。TCP和UDP都属于这层的协议。
-
总而言之:应用层提供了要发送的数据,传输层真正传输数据,而且保证了数据能够正确的传输。
传输层之TCP报文
- 客户端和服务端能够解析TCP信息是因为都遵循TCP报文格式,正常的TCP报文格式比较复杂,这里化繁为简,只是把其中跟握手关联比较紧密的展示出来,与本篇内容无关的暂且不表。

- 序列号(Seq):占32位,发送方到接收方的标记。
- 确认号(Ack):占32位,是接收方回复的标记,Ack=Seq+1
- Flags:常用的ACK、PSH、RST、SYN、FIN。ACK表示确认收到消息,PSH发送消息的标志,RST重置连接,SYN发起连接,FIN结束连接。
- DATA:是传递的数据,一般在握手阶段数据的长度都位0
TCP握手和挥手
TCP三次握手
- 由客户端发起,大致流程如下:

- 客户端发起连接
SYN=1,seq=x - Server收到之后响应
SYN=1 ACK=1表示同意建立连接并确认收到连接请求,此时Seq=y Ack=x+1 - 客户端收到之后回应
ACK=1并相应给服务端Ack=y+1 Seq=x+1,完成之后连接就建立了,可以开始传输数据 - 为什么是三次握手不是四次?因为在第二步的时候把
SYN和ACK同时传给了客户端,就节约了一次握手的过程,为什么两次不可以? 如果只有两次没有最后一次确认创建连接,第二次服务端就直接建立连接,但是客户端并不一定收到第二次的反馈,则会导致服务端一直等待连接,浪费连接资源
TCP四次挥手
- 挥手是客户端主动发起,数据传输完成关闭连接,大致流程如下:

- 客户端发送
FIN=1结束连接请求,携带Seq=x发送给服务端 - Server收到请求相应给客户端
ACK=1,Seq=y,Ack=x+1进入ClOSE_WAIT阶段,这个阶段服务端可能还有数据要传送给客户端,所以进入等待阶段 - 在Server数据发送完成后,Server给客户端发送
ACK=1 Ack=x+1 Seq=z - Client收到之后相应给服务端
ACK=1 Seq=x+1 Ack=z+1,这样就完成了四次挥手(画外音:这里client也可能进入2MSL阶段,为什么?) - 四次挥手能够保证数据传输正确的完成。为什么是四次挥手,三次挥手不行吗?因为三次就少了一次服务端
FIN=1,ACK=1的过程,想象下这个时候如果服务端的数据还没有传递完成,客户端已经关闭了连接则会出现数据丢失,所以需要四次来保证数据的完成传送 - 可以看到不管是三次握手还是四次挥手的过程都有几次的网络通讯,如何来节约网络通讯的开销则是对于一个高并发系统不得不考虑的问题。接下来要说的性能优化的一种:池化技术
池化技术
- 说了这么多理论的东西,是不是有点头晕了,反正TCP我现在还没全明白,不过理解接下来的流程还是绰绰有余,下面实操一把,把理论的东西运用到实际的编程中去。在开发的过程中许多地方用到了池化技术,比如:连接池、线程池和对象池等等。通过对象的复用来提高系统处理效率。
性能优化之HTTP重用TCP连接(不能完全算是连接池)
- 在Http1.1协议中默认使用的
Connection:keep-alive属性来保持跟服务端的连接,通常浏览器第一次访问会缓存某个请求的连接信息,后面继续访问同个请求,则直接重用连接(注意这里是重用tcp连接)。当然这个连接(tcp连接)只能保持一段时间,当超过时间之后还是要再次重新初始化连接。从下图两次从浏览器中截取的图片的对比明显可以看出前后的加速效果,第一次耗时65.23ms,第二次耗时0.91ms,又是明显呀!

1268

被折叠的 条评论
为什么被折叠?



