深入分析javaweb技术内幕之网络I/O工作机制

数据从一台主机发送到网络中的另一台主及需哟啊经过很多步骤。首先需要有相互沟通的意向。其次要有能够沟通的物理渠道(物理链路):是通过电话,还是直接面对面交流。再次,双方见面时语言要能够交流,而且双方说话的步调要一致,明白什么时候该自己说话,什么时候该对方说话(通信协议)。

2.3.1 TCP状态转化

在讨论如何进行Socket通信之前,我们先看看如何建立和关闭一个TCP连接,TCP连接的状态转换如图:

深入分析javaweb技术内幕之网络I/O工作机制


(1)CLOSED:起始点,在超时或者连接关闭时进入此状态。

(2)LISTEN:Server端在等待连接时的状态,Server端为此要调用Socket、bind、listen函数,就能进入此状态。这成为应用程序被动打开(等待客户端来连接)。

(3)SYN_SENT:客户端发起连接,发送SYN给服务器端。如果服务器不能连接,这直接进入CLOSED状态。

(4)SYN-RCVD:与3对应,服务器端接受客户端的SYN请求,服务器端由LISTEN状态进入SYN-RCVD状态。同时服务器端要回应一个ACK,发送一个SYN给客户端;另外一种情况是,客户端在发起SYN的同事接收到服务器端的SYN请求,客户端会由SYN-SENT转换到SYN-RCVD状态。

(5)ESTABLISHED:服务器端和客户端在完成3次握手后进入状态,说明已经可以开始传输数据了。

(6)FIN-WAIT-1:主动关闭的一方,由状态5进入此状态。具体动作是发送FIN给对方。

(8)CLOSE-WAIT:接收到FIN以后,被动关闭的一方进入此状态。具体动作是再接收到FIN的同时发送ACK。

(7)FIN-WAIT-2:主动关闭的一方,接收到对方的FIN ACK,进入此状态。由此不能再接收对方的数据,但是能够向对方发送数据。

(9)LAST-ACK:被动关闭的一方,发起关闭请求,由状态8进入此状态。具体动作是发送FIN给对方,同时再接收到ACK时进入CLOSED状态。

(10)CLOSING:两边同时发起关闭请求时,会由FIN-WAIT-1进入此状态。具体动作时接收到FIN请求,同时响应一个ACK。

(11)TIME-WAIT:这个状态比较复杂,也是我们最常见的一个连接状态,有3个状态都可以转化为此状态。

----------------------------------------------------------------------------------------------------------------------------------

注意:为什么建立连接只要三次握手,而断开连接就需要4次握手呢?

其实建立连接,只要发送了ACK包,两边连接都可以通畅了,并且建立连接只能是客户端请求服务端。

而断开连接可能是客户端发起,服务端发起,或同时发起。如果只有三次握手,就可能会造成丢包引起的,一直收不到信息无法关闭连接。

---------------------------------------------------------------------------------------------------------------------------------

搞清楚TCP连接的几种状态转换对我们调试网络程序非常有帮助的。例如,当我们在压测一个网络程序时可能遇到CPU、网卡、带宽等都不是瓶颈,但是性能就是呀不上去的情况,你如果观察一下网络连接情况,看看当前的网络都出于什么状态,可能就会发现由于网络连接的并发数不够导致连接都出于TIME_WAIT状态,这时就要做TCP网络参数调优了。

查看TCP网络情况的方式时netstat,这里有篇文章做了介绍:

netstat查看当前网络下TCP的各种状态

2.3.2 影响网络传输的因素

将一份数据从一个地方正确地传输到另一个地方所需要的时间我们称之为响应时间。影响这个响应时间的因素有很多。

  • 网络带宽:所谓带宽就是一条物理链路在1s内能够传输的最大比特数,注意这里时比特(bit)而不是字节数,也就是b/s。网络带宽肯定时影响数据传输的一个关键环节,因为在当前的网络环境中,平均网络带宽只有1.7Mb/s左右。
  • 传输距离:也就是数据在光纤中要走的距离,虽然光的传播速度很快,但也是有时间的,由于数据在光纤中的移动并不是走直线的,会有一个折射率,所以大概是光的2/3,这个时间也就i是我们通常所说的传输延时。传输延时是一个无法笔迷爱你的问题,例如,你要给在杭州和青岛的两个机房的一个数据库进行同步数据操作,那么比定位存在约30ms的一个延时。
  • TCP拥塞控制:我们知道TCP传输是一个“停-等-停-等”的协议,传输方和接收方的步调要一致,要达到步调一致就要通过拥塞控制来调节。TCP在传输时会设定一个“窗口(BDP,Bandwidth Delay Product)”,这个窗口的大小时由带宽和RTT(Round-Trip Time,数据在两端的来回时间,也就是响应时间)决定的。计算的 公式时带宽(b/s)* RTT(s.)通过这个值可以得出理论上最优的TCP缓冲区的大小。Linux2.4已经可以自动地调整发送端的缓冲区的大小,而到Linux2.6.7时接收端也可以自动调整了。

关于TCP缓冲区的理解,这里有篇博文:https://blog.csdn.net/yusiguyuan/article/details/21439633