tcp协议报文和三次握手与四次挥手
tcp协议:
tcp是面向连接、可靠的进程到进程之间的协议。tcp提供全双工服务:即:数据可在同一时间双向传输。
tcp报文段首部格式:
各字段含义:
源端口号:16位字段,为发送端进程对应的端口号
目标端口:16位字段,为接收端进程对应的端口号,接收方接收到数据包之后根据这个字段确定将数据发送给对应程序来处理
序号:32位字段,当tcp从进程中接收到数据之后,就会把他存储在发送缓存中。并对每一个字节进行编号,形成的序列号。特点如下:
会生成一个随机数作为第一个字节的编号,成为序列号(ISN),范围是:0-(232-1)
tcp每个方向的编号都是相互独立的
当字节都被编上号之后,tcp就给每个报文段指定一个序号,序号就是该报文段中第一个字节的编号
确认号:32位字段,确认号是对发送端的确认信息,用它来告诉发送端这个序号之前的数据段都已经收到,如确认号是x,那么表示收到前x-1个数据段
首部长度:用它可以确定首部数据结构的字节长度,一般情况下tcp的首部长度是20字节,但是首部长度最长可以扩展至60字节
保留:保留作为扩展使用。
控制位:tcp的连接和断开都受这六个控制位指挥。含义如下:
URG:紧急指针有效位
ACK:只有当ACK=1时,确认序列号字段才有效,当ACK=0时,确认号字段无效。
PSH:标志位为1时要求接收方尽快将数据段送达应用层。
RST:当RST的值为1的时候通知重新建立tcp连接。
SYN:同步序号为,tcp需要建立连接时将这个值设为1。
FIN:发送端完成发送任务,当tcp完成数据传输需要断开连接时,提出断开连接方,将此控制位设置成1。
窗口值:本地可接受数据段的数目,这个值的大小随着网络是可变的。当网络畅通时,值变大可加快传输速度,网络不稳定时,值变小可保证传输数据的可靠性;tcp协议中的流量控制就是更改窗口值来实现的
校验和:用来做差错控制,发送tcp报文前计算一遍校验和。当接收端收到数据后再做一次校验,当两个值一致时,说明数据是没问题的。
紧急指针:和URG配合使用,当URG=1时有效;
选项:在tcp首部可以有多达40字节的可选信息。
tcp的连接与断开:
在数据通信之前,发送端与接收端要建立连接;等数据发送结束后,双方在断开连接。tcp连接的每一方都是由一个IP和端口组成的、
三次握手与四次挥手如图:
假设服务器监听80端口。由客户端进行访问
三次握手过程:
第一次:
客户端使用随机的端口向服务器的80端口发起连接请求,此过程中典型的标志就是tcp的SYN控制位为1.其他五个控制位全为0;
第二次:
由两部分完成:
1、服务端收到客户端发送的连接请求,向客户端回复确认信息。此过程中典型的标志就是TCP的ACK控制位为1,其他五个控制位全为0,而且序列号是客户端初始序列号+1;
2、服务端同时也向客户端发送一个连接请求,此过程中典型的标志位与第一次握手中一样。即TCP的SYN控制位是1,其他五个控制位为0。
为提高通信效率,这两部分是在同一个数据包中实现。
第三次:
客户端收到服务端的回复(确认和请求),也需要向服务端发送一个确认信息;此过程的典型标志就是tcp的ACK控制位为1,其他五个控制位全为0;确认序列号为服务端的初始序列号+1
三次握手完成,tcp连接建立成功。使用命令netstat -an 命令可查看状态为:ESTABLISHED
三次握手状态监控:
服务器创建socket后开始监听,变为LISTEN状态。客户端请求建立连接,向服务器发送SYN报文,客户端的状态变为SYN_SENT。服务器收到客户端的报文后向客户端发送ACK和SYN报文,此时服务器的状态变为SYN_RCVD。然后,客户端收到ACK、SYN,就向服务器发送ACK,客户端状态变为ESTABLISHED,服务器收到客户端的ACK后也变为ESTABLISHED。此时,3次握手完成,连接建立!
四次挥手过程:
第一次:
客户端向服务器发送控制位FIN和ACK位置为1的tcp报文
第二次:
服务器向客户端返回控制位ACK为1的tcp报文
此时处于一个半关闭的状态,客户端终止发送数据,只回复ACK确认报文,不再发送数据报文,但是扔然可以接收数据。当服务器发送完数据之后,向客户端发送FIN报文并收到ACK确认,这样就完全关闭了这个tcp连接
第三次:
服务器向客户端发送控制位FIN和ACK位置为1的tcp报文
第四次:
客户端向服务器返回控制位ACK为1的tcp报文
四次挥手状态监控:
由于tcp连接是全双工的,断开连接会比建立连接麻烦一点点。客户端先向服务器发送FIN报文,请求断开连接,其状态变为FIN_WAIT1。服务器收到FIN后向客户端发生ACK,服务器状态变为CLOSE_WAIT。客户端收到ACK后就进入FIN_WAIT2状态。此时连接已经断开了一半了。如果服务器还有数据要发送给客户端,就会继续发送。直到发完了,就发送FIN报文,此时服务器进入LAST_ACK状态。客户端收到服务器的FIN后,马上发送ACK给服务器,此时客户端进入TIME_WAIT状态,再过了2MSL长的时间后进入CLOSED状态。服务器收到客户端的ACK就进入CLOSED状态。
至此,还有一个状态没有提及:CLOSING状态。CLOSING状态表示客户端发生了FIN,但没有收到服务器的ACK,却收到了服务器的FIN。这种情况发生在服务器发送的ACK丢包的时候,因为网络传输有时会有意外。
使用命令查看tcp网络连接状态:
netstat -n |grep 端口 | awk '/^tcp/ {++a[$NF]} END {for (v in a) print v,a[v]}'
状态详解:
listen:侦听客户端的连接请求
syn_send:客户端发送连接请求等待确认连接
syn_recv :服务端收到一个连接请求,给对方响应确认(syn+ack同时为1)时的状态
established:一个连接的打开,数据正常传输的状态
fin_wait1:客户端主动发出fin关闭连接请求之后等待确认
fin_wait2:客户端接收到关闭连接的ACK确认之后状态(半关闭状态)只接受数据并发送ACK确认,不发送数据
close_wait:服务器接受到FIN后,发出ACK以回应FIN请求之后等待本地发起连接中断请求的状态
closing:主动关闭端发送FIN请求之后等待对方对连接中断的确认,(正常是看不到此状态)
last_ack:被动关闭端,接收到文件结束符之后向主动关闭端发送fin请求等待ACK时的状态
time_wait:(2MSK状态)主动关闭端接收到FIN后,发送ACK进入time-wait状态。防止对方没有收到最后的ACK确认报文,确保双方都可以正常结束。这个期间可以重启启动服务连接但不能发送数据
closed:被动关闭端接受到ACK包之后的状态。代表连接结束。