1:TCP建立连接的过程
1.1建立连接的图片如下
上诉的大体流程如下图所示,只是报文的格式略有差异
1.2实例ubuntu系统下的telnet www.163.com 80
可以发现建立了连接:经理了三次握手
<1>15:44:54.672770 IP 192.168.43.146.47652 > 112.84.104.148.80: Flags [S], seq 2468862156,
win 29200, options [mss 1460,sackOK,TS val 4416678 ecr 0,nop,wscale 7], length 0
客户主动发起建立连接,为主动打开
SYN:
表示建立TCP连接,必须为1
FLAG表示标志:
S,SYN表示SYN同步讯号
F,FIN发送方完成数据发送
R,RST复位连接
P,PSH尽可能快的将数据送往接受进程
.,以上几个标志是0
seq 2468862156:
表示序号,如果是第一个带有SYN的数据报,则这个序号是取自ISN序号,这个字段并没有预先加1,而是在后来的确认报文中加1,这说明SYN占了一个序号,当后来的数据字节,比如说发送了P 13:56,则返回确认的时候是ack 56,这里返回下一次应该发送的字节,但是
win29200:
其中的win大小位窗口大小,表示可以接纳多少数据
options:TCP选项
里面的mss表示对方最大可以一次发多大的TCP数据报中的数据不分
length:
里面的0表示TCP的数据报中的数据是0,没有数据
<2>15:44:54.724993 IP 112.84.104.148.80 > 192.168.43.146.47652: Flags [S.], seq 4220088274,
ack 2468862157, win 14600, options [mss 1400,nop,nop,sackOK,nop,wscale 7], length 0
并且这是服务器所发送的一个SYN,被称为被动打开
ack:
表示对上述接收到的数据报序号进行确认
1.3当客户发起关闭的时候
看图是进行四次协议的交换
2:建立连接超时
发生的情形,服务器没有处于正常状态,可以断开服务器电缆线进行模拟
列如有
0.0 bsdi.1024>svr4.dicard:S 9233:9233(0) win 4096 <mss 1024>
5.814797(5.81) bsdi.1024>svr4.dicard:S 9233:9233(0) win 4096 <mss 1024>
29.81543 (24) bsdi.1024>svr4.dicard:S 9233:9233(0) win 4096 <mss 1024>
为什么第一次是5.81秒,而不是具体的整数
而第二次是24,是具体的表示
因为第一次的时候软件在一个具体的定时间隔中的任意位置中开始计时,在随后的11个周期内是准确的时间,这就造成时间不是以整数的,而是有小数点的5.81秒
第二次因为在完整的,所以说是直接完成的24s
3:半关闭的情形
3.1概念:即当一方关闭他的发送,即发送一个FIN报文的时候,就可以关闭本方的发送,但是并没有关闭本方的接受,所以说对方依旧可以发送数据给本方,当对方发送一个FIN的时候,再进行关闭对方的发送
4:TCP状态的变迁图
以上的图可以对应以下的流程图,以下的图就是正常的建立TCP连接和正常的关闭TCP连接
这两幅图应该这样对看,首先图二对应的是正常的状态变迁图,图二的最左面和最右面表示的是状态,比如说图二的SYN_SENT后面跟着SYN j就对应着图一SYN_SENT和上面的粗黑线,即图二的每一方的发送线对应着图一的状态框的上方线
4.1 2MSL超时
msl,即为每一个报文最大的生存时间通常是30s,1min,2min,如果执行主动关闭,并且再发回最后一个ACK的时候,即应该开始2MSL的等待(如上图二的TIME_WAIT下面的ack N+1),可以使另一方在MSL的时间内超时,并发回FIN,使原本的发送方发送一个ack
在2MSL等待的时间内,原本的插口对是不允许在使用的,否则会造成原来的报文被新的连接重新接受,造成错误
但是当服务器执行主动关闭,并且有指定了SO-REUSEADDR即可以重新使用这个插口对(但是应该要求新的序号应该大于原来连接的序号)
4.2平静等待时间
对于某个连接较早替身(和当前的TCP连接使用相同的插口对,但是已经终止的连接)迟到的报文,
2MSL可以防止他被解释成当前连接的报文,但是这个情况只有处于2MSL的主机为正常的状态的条件下才有用,如果出现差错,他会在MSL内进行重启,如果重启,他会利用原来的插口对进行连接?如果这样就会造成报文的被误解,因此为了避免这种办法,我们应该规定在重启后的MSL秒内都不能建立任何连接
4.3FIN_WAIT_2
主动关闭方已经发出了FIN,并且被动关闭方也已对它进行ACK确认,那么主动方进入FIN_WAIT_2状态。只有当被动方的进程完成这个关闭(发出FIN包),主动方发出ack,主动方才从FIN_WAIT_2进入TIME_WATI状态。
如果被动方一直不发出FIN包,这意味着主动和被动方分别永远保持FIN_WAIT_2和CLOSE_WAIT状态,并一直保持这个状态直到应用层决定进行关闭。(许多伯克利实现采用以下方法来防止这种FIN_WAIT_2状态的无限等待,如果执行主动关闭的应用层将进行全关闭,而不是半关闭,表示它不想接收数据,就设置一个定时器,如果这个连接空闲超过10分钟75秒,那么TCP将进入CLOSED状态)
5:复位报文段
5.1连接不存在的端口:
一般来说,无论何时一个报文段发往基准的连接出现错误,TCP都会发出一个复位报文段。产生复位的一种常见情况是当连接请求到达时,目的端口没有进程正在监听,例如当一个数据报达到目的端口时,该端口没在使用,它将产生一个端口不可达的信息(对于UDP),而TCP则使用复位。
5.2异常终止一个连接:
终止连接有2个方式,其中一个是正常方式:一方发送FIN,也称为有序释放,正常情况下没有任何数据丢失。但也有可能发送一个复位报文段而不是FIN来中途释放一个连接,称为异常释放。
异常终止一个连接对应用程序来说有2个优点:
1)丢弃任何待发数据并立即发送复位报文段
2)RST的接收方会区分另一端执行的是异常关闭还是正常关闭。
需要注意的是RST报文段不会导致另一端产生任何响应,另一端根本不进行确认。收到RST的一方将终止连接,并通知应用层连接复位!!
6:检测半打开连接
如果一方已经关闭或异常终止连接而另一方却还不知道,我们将这样的TCP连接称为半打开的(Half-Open)。任何一端的主机异常都可能导致发生这种情况。只要不打算在半打开连接上传输数据,仍处于连接状态的一方就不会检测另一方已经出现异常。
半打开连接的另一个常见原因是当客户主机突然掉电而不是正常的结束客户应用程序后再关机。此时如果服务器又重新启动,它将丢失复位前连接的所有信息,因此它不知道数据报文段中提到的连接。此时TCP处理的原则是接收方以复位作为应答。
7:同时打开
两个应用程序同时彼此执行主动打开的情况是可能的,TCP特意设计可以处理同时打开,对于同时打开它仅建立一条连接而不是两条连接。
同时打开时,两端几乎同时发送SYN,并进入SYN_SENT状态。当每一端收到SYN时,状态变为SYN_RCVD,同时它们都再发SYN并对收到的SYN进行确认。当双方都收到SYN相应的ACK时,状态都变迁为ESTABLISH。
一个同时打开的连接需要交换4个报文段,比正常的三次握手多1个,如下图所示:
8:同时关闭
双方同时执行主动关闭是可能的,TCP协议也允许这样的同时关闭。
当应用层发出关闭命令时,两端均从ESTABLISH变为FIN_WAIT1,这将导致双方各发送一个FIN,两个FIN经过网络传送后分别到达另一端。收到FIN后,状态由FIN_WAIT1变迁到CLOSING,并发达最后的ACK,状态变化为TIME_WAIT。
同时关闭与正常关闭使用的段交换数据相同。