目录
一.TCP协议是什么?
1.TCP协议定义
TCP是面向连接的、可靠的进程到进程通信的协议
TCP提供全双工服务,即数据可在同一时间双向传输
2.TCP特性
- 工作在传输层
- 面向连接协议
- 全双工协议
- 半关闭
- 错误检查
- 将数据打包成段,排序
- 确认机制
- 数据恢复,重传
- 流量控制,滑动窗口
- (可移动至八.TCP和UDP的特性,与UDP特性进行对比)
3.TCP报文格式
报文格式解析:
源端口、目标端口:计算机上的进程要和其他进程通信是要通过计算机端口的,而一个计算机端口某个时刻只能被一个进程占用,所以通过指定源端口和目标端口,就可以知道是哪两个进程需要通信。源端口、目标端口是用16位表示的,可推算计算机的端口个数为2^16个,即 65536 (0-65535)
序列号:表示本报文段所发送数据的第一个字节的编号。在TCP连接中所传送的字节流的每一个字节都会按顺序编号。由于序列号由32位表示,所以每2^32个字节,就会出现序列号回绕,再次从0 开始 无限循环
确认号:(ack)表示接收方期望收到发送方下一个报文段的第一个字节数据的编号。也就是告诉发送方:我希望你(指发送方)下次发送的数据的第一个字节数据的编号为此确认号:传输是否有问题?
数据偏移/首部长度:表示TCP报文段的首部长度,共4位,由于TCP首部包含一个长度可变的选项部分,需要指定这个TCP报文段到底有多长。它指出 TCP 报文段的数据起始处距离 TCP 报文段的起始处有多远。该字段的单位是32位(即4个字节为计算单位),4位二进制最大表示15,所以数据偏移也就是TCP首部最大60字节
控制位:确定两台主机处于什么状态
URG(紧急位):表示本报文段中发送的数据是否包含紧急数据。后面的紧急指针字段(urgent pointer)只有当URG=1时才有效
ACK(确认位):表示是否前面确认号字段是否有效。只有当ACK=1时,前面的确认号字段才有效。TCP规定,连接建立后,ACK必须为1,带ACK标志的TCP报文段称为确认报文段
PSH(急切位):提示接收端应用程序应该立即从TCP接收缓冲区中读走数据,为接收后续数据腾出空间。如果为1,则表示对方应当立即把数据提交给上层应用,而不是缓存起来,如果应用程序不将接收到的数据读走,就会一直停留在TCP接收缓冲区中
RST(重置位):如果收到一个RST=1的报文,说明与主机的连接出现了严重错误(如主机崩溃),必须释放连接,然后再重新建立连接。或者说明上次发送给主机的数据有问题,主机拒绝响应,带RST标志的TCP报文段称为复位报文段
SYN(同步位):在建立连接时使用,用来同步序号。当SYN=1,ACK=0时,表示这是一个请求建立连接的报文段;当SYN=1,ACK=1时,表示对方同意建立连接。SYN=1,说明这是一个请求建立连接或同意建立连接的报文。只有在前两次握手中SYN才置为1,带SYN标志的TCP报文段称为同步报文段
FIN(断开位):表示通知对方本端要关闭连接了,标记数据是否发送完毕。如果FIN=1,即告诉对方:“我的数据已经发送完毕,你可以释放连接了”,带FIN标志的TCP报文段称为结束报文段
窗口大小:表示现在允许对方发送的数据量,也就是告诉对方,从本报文段的确认号开始允许对方发送的数据量,达到此值,需要ACK确认后才能再继续传送后面数据,由Window size value * Window size scaling factor(此值在三次握手阶段TCP选项Window scale协商得到)得出此值
校验和:提供额外的可靠性紧急指针:标记紧急数据在数据字段中的位置
选项部分:其最大长度可根据TCP首部长度进行推算。TCP首部长度用4位表示,选项部分最长为:(2^4-1)*4-20=40字节
4.常用的TCP端口号及其功能
二.TCP三次握手
第一次握手PC1发送请求报文给PC2
发送seq(序列号随机的)=x 控制位SYN=1的报文。
第二次握手PC2回复PC1请求连接报文
SYN + ack (确认号) 报文
seq(序列号) = y #pc2随机生成的序列号
ack=x+1 #pc2 希望pc1 下次回复的时候,序号是x+1
控制位 SYN=1 请求连接
ACK=1 同意连接
第三次握手PC1 回复PC2同意连接的报文
ACK报文(确认报文)
seq = x+1 序号是从PC2那里得来的
ACK = 1 同意连接
ack = y + 1#希望下次发送真实数据时,报文的序列号y+1
三.TCP四次挥手
第一次挥手:A向B发出释放连接请求的报文,其中FIN(终止位) = 1,seq(序列号)=u;
在A发送完之后,A的TCP客户端进入FIN-WAIT-1(终止等待1)状态。此时A还是可以进行收数据的
第二次挥手:B在收到A的连接释放请求后,随即向A发送确认报文。其中ACK=1,seq=v,ack(确认号) = u +1;
在B发送完毕后,B的服务器端进入CLOSE_WAIT(关闭等待)状态。
此时A收到这个确认后就进入FIN-WAIT-2(终止等待2)状态,等待B发出连接释放的请求。此时B还是可以发数据的。
(如果 B 直接跑路,则 A 永远处与这个状态。TCP 协议里面并没有对这个状态的处理,但 Linux 有,可以调整 tcp_fin_timeout 这个参数,设置一个超时时间。)
第三次挥手:B->A:当B已经没有要发送的数据时,B就会给A发送一个释放连接报文,其中FIN=1,ACK=1,seq=w,ack=u+1,
在B发送完之后,B进入LAST-ACK(最后确认)状态。
第四次挥手:当A收到B的释放连接请求时,必须对此发出确认,其中ACK=1,seq=u+1,ack=w+1;
A在发送完毕后,进入到TIME-WAIT (时间等待)状态。B在收到A的确认之后,进入到CLOSED(关闭)状态。在经过时间等待计时器设置的时间之后,A才会进入CLOSED状态。
有限状态机(扩展)
CLOSED 没有任何连接状态
LISTEN 侦听状态,等待来自远方TCP端口的连接请求 (服务开启 http(进程) 80端口在帮进程 看着 有没有人找 http )
SYN-SENT 在发送连接请求后,等待对方确认
SYN-RECEIVED 在收到和发送一个连接请求后,等待对方确认
ESTABLISHED 代表传输连接建立,双方进入数据传送状态
FIN-WAIT-1 主动关闭,主机已发送关闭连接请求,等待对方确认
FIN-WAIT-2 主动关闭,主机已收到对方关闭传输连接确认,等待对方发送关闭传输连接请求
TIME-WAIT 完成双向传输连接关闭,等待所有分组消失
CLOSE-WAIT 被动关闭,收到对方发来的关闭连接请求,并已确认
LAST-ACK 被动关闭,等待最后一个关闭传输连接确认,并等待所有分组消失
CLOSING 双方同时尝试关闭传输连接,等待对方确认
客户端先发送一个FIN给服务端,自己进入FIN_WAIT_1状态,这时等待接收服务端报文,该报文会有三种可能:
只有服务端的ACK
只有服务端的FIN
基于服务端的ACK,又有FIN
四.UDP协议
无连接、不可靠的传输协议
花费的开销小
UDP报文的首部格式:
源端口号(16) | 目标端口号(16) |
UDP长度(16) | UDP校验和(16) |
五.TCP和UDP的特性
目录
实验步骤如下:
1.打开Wireshark抓包软件,点击interface List。
2.选择与SecureCRT相连的虚拟机网卡VMnet1。
3.在Centos系统终端里输入#ip addr#的命令,找到其IP地址。
4.按如下图所示步骤进行SecureCRT软件的连接。
5.输入root账户的密码。
6.这时我们可以就看到三次握手的数据包了
7.第一次握手。源IP:192.168.29.1 目标IP:192.168.29.2。
源端口:54949 目标端口:22
8.第二次握手。源IP:192.168.29.2 目标IP:192.168.29.1
源端口:22 目标端口:54949
9.第三次握手。源IP:192.168.29.1 目标IP:192.168.29.2
源端口:54949 目标端口:22
10.在SecureCRT里输入#init 0#命令,抓包软件里就能看到四次挥手了。
11.第一次挥手。源IP:192.168.29.2 目标IP:192.168.29.1
源端口:22 目标端口:61668
12.第二次挥手。源IP:192.168.29.1 目标IP:192.168.29.2
源端口:61668 目标端口:22
13.第三次挥手。源IP:192.168.29.1 目标IP:192.168.29.2
源端口:61668 目标端口:22
14.第四次挥手。源IP:192.168.29.2 目标IP:192.168.29.1
源端口:22 目标端口:61668
七.相关问题
1.TCP连接为什么是三次握手?
三次握手的目的是建立可靠的通信通道,简单来说就是数据的发生与接收,而三次握手最主要的目的就是双方确认自己与对方的发送与接收是否正常
第一次握手:客户机什么都不能确认,服务机确认了对方发送正常,自己接收正常
第二次握手:客户机确认了:自己发送、接收正常,对方发送正常、接收正常;服务机确认了:对方发送正常,自己接收正常
第三次握手:客户机确认了:自己发送、接收正常,对方发送正常、接收正常;服务机确认了:对方发送正常,接收正常,自己发送正常,接收正常。
那么明明两次就可以建立连接的为什么还要加第三次的确认?
如果发送两次就可以建立连接话,那么只要客户端发送一个连接请求,服务端接收到并发送了确认,就会建立一个连接。
可能出现的问题:如果一个连接请求在网络中跑的慢,超时了,这时客户端会重发请求,但是这个跑的慢的请求最后还是跑到了,然后服务端就接收了两个连接请求,然后全部回应就会创建两个连接,浪费资源!
如果加了第三次客户端确认,客户端在接受到一个服务端连接确认请求后,后面再接收到的连接确认请求就可以抛弃不管。
结合流程解释:
1.刚开始客户端和服务端都是关闭状态,服务端会一直处在监听状态,监听是否有建立连接的请求。
2.客户端需要建立连接时,会发送确认连接报文,此报文是同步报文SYN=1,同时生产一个随机序列号seq=x,这是第一次握手。
第一次握手,客户端发送同步报文到服务端,客户端知道自己有发送数据能力,不知道服务端是否有发送、接受数据能力。
3.当服务端接收到连接请求报文时,会发送一个同步报文确认报文,此报文SYN=1,并且ACK=1(大写ACK表示报文为确认报文),同时服务端也会生成一个随机序列号seq=y,并且将ack设置为x+1(x是客户端发送的同步报文序列号),确认报文回传给客户端,这是第二次握手。
第二次握手,服务端收到同步报文,并回复确认同步报文,此时,服务端知道自己有接收、发送数据能力,并且客服端有发送数据能力,但不知道客户端是否有接收数据能力。
4.当客户端收到服务端的ACK报文后,会回复一个ACK确认报文,用于确认确认报文已收到,此报文 ACK = 1,seq = x + 1, ack = y + 1(y是确认报文序列号),这是第三次握手 。
第三次握手,当客户端收到确认同步报文后,知道服务端具备发送、接收能力,也知道自己具备,但是服务端只知道客户端具备发送能力,还不知道也有接收能力,所以需要发送确认报文,告诉服务端自己具备接收能力。
当三次握手流程结束后,客户端服务端都知道自己和对方具备发送、接收数据能力,建立连接完成,就可以进行数据传输了。
所以两次握手是无法满足以上条件的, 因为服务端并不知道客户端是具备接收数据的能力,需要第三次握手,客户端告知服务端自己有接收能力。
2.TCP连接为什么是四次挥手?
三次握手是为了建立可靠的数据传输通道,四次挥手是为了保证等数据传输完再关闭连接,保证双方都达到关闭连接的条件才能断开。
1.客户端发起 FIN=1 断开连接的报文,携带随机生成的 seq=u,发送给服务端,并且自己处于 FIN-WAIT状态,这是第一次挥手。
第一次挥手客户端发起关闭连接的请求给服务端;
2.服务端接收到 FIN 报文后,回复一个确认报文,其中 ACK = 1,随机生成一个 seq=v,以及 ack=u+1(u为客户端发送报文的序列号),这是第二次挥手。
第二次挥手:服务端收到关闭请求的时候可能这个时候数据还没发送完,所以服务端会先回复一个确认报文,表示自己知道客户端想要关闭连接了,但需要等待数据传输完;
3.当服务端数据发送完了过后,再发送一个 FIN 报文给客户端,通知客户端,服务端准备关闭连接了,此报文 FIN=1,ACK=1,ack=u+1(u为客户端发送报文的序列号),seq=w,这是第三次挥手。
第三次挥手,当数据传输玩,服务端会主动发送FIN报文,告知客户端,标识数据已发送万传给你,服务端准备关闭连接了。
4.当客户端收到 FIN 确认报文时再发送一个FIN 的确认报文,其中 ACK = 1,seq = u + 1,ack = w + 1(w为服务端发送报文的序列号),并进入 TIME-WAIT 状态,当等待 2MSL ( 报文最大生存时间 *2)后关闭连接,这是第四次挥手。
第四次挥手,当客户端收到服务端的FIN报文后,会回复ACK报文,告知服务端自己知道了,在等待一会就关闭连接。
3.为什么握手三次,挥手却要四次?
没有数据传输时,服务端的SYN和ACK报文可以一起发送,但是挥手时有数据传输,ACK和FIN报文不能同时发送,需要分为两步,所以多了一步流程。
4.为什么客户端在第四次挥手后还会等待2MSL?
等待是因为保证服务端接收到了ACK报文,因为网络是复杂的,ACK报文可能会丢失,如果服务端没接收到ACK报文的话,会重新发送FIN报文,只有当客户端等待了2MSL都没有收到重新发送的FIN报文时,才表示服务端是正常接收到了ACK报文,这个时候客户端就能关闭了。