TCP是什么?
TCP是面向连接的、可靠的传输层协议。
什么是面向连接?
面向连接就是先建立连接,再传输数据。
我们先来了解一下TCP的报文格式。
1byte=8bits TCP固定长度20Bytes
- Source port(源端口号/未知端口号):由于计算机编码都是二进制,2的十六次方为65536,所以端口号取值范围是0-65535,一共65536个数字。端口号可以提高IP地址的复用率。源端口号在1024-65535中随机产生 。
- Destination port(目的端口号/已知端口号):取值为1-1023,该范围内的端口号已经被分给应用层协议。(端口号0不用)
- Sequence number(序列号) Acknowledgement number(确认号 用于确认对方发来的最后一条报文):他们确保了TCP通信过程中的回馈机制,保证报文的可靠传输。
- Control(控制位/标志位):里面有3个需要我们这次着重认识一下。
SYN:同步位。当SYN置位为1(0变1)时,代表我要和你建立TCP链接。
ACK:确认位。当ACK置位为1(0变1)时,代表本报文有确认性质,是对上一条报文进行确认。
FIN:终止位。当FIN置位为1(0变1)时,代表我要请求断开TCP链接。
- Window(窗口大小):之后我们再来说这个滑动窗口机制。
以上是在TCP报文格式中我们需要知道的。
我们再来看一下报文五元组。
五元组:SIP(源IP地址)+DIP(目标IP地址)+协议类型(TCP/UDP)+Sport(源端口号) +Dport(目标端口号)
三次握手
TCP在传输数据之前都要进行三次握手来保证双方的可靠性。此过程不携带任何应用层数据。
【假设Client(客户机)的IP地址为1.1.1.1,Http sever(服务器)的IP地址为2.2.2.2】
SIP 1.1.1.1 DIP 2.2.2.2 TCP
Sport x Dport 80
seq=m ack=0
flag:SYN=1
第一排不用说叭,我们往后看~
- Sport是Source port(源端口号/未知端口号)的缩写,还记得前面提到的吗,源端口号在1024-65535中随机产生,这里我们就假定了个x。
- Dport是Destination port(目的端口号/已知端口号)的缩写,这里为80是因为http协议的默认端口号就是80。
- seq是Sequence number(序列号)的缩写,先随机生成一个m。
- ack是Acknowledgement number(确认号)的缩写,这里不需要作出任何确认,所以为0。
- flag是标志的意思,代表控制位/标志位。此时SYN(同步位)置位为1,客户端向服务器请求建立TCP链接。
SIP 2.2.2.2 DIP 1.1.1.1
TCP
Sport 80 Dport x
seq=n ack=m+1
flag:SYN=1 ACK=1
现在服务器回了一条
- SIP和DIP互换了,Sport和Dport互换了,这是当然叭~
- 这是服务器发的第一条,seq(序列号)随机生成一个n。
- 这时候ack(确认号)=m+1,m+1是什么?是上一条报文的seq(序列号)然后再+1确认,确认收到对方的报文。
- 此时服务器也向客户端请求建立TCP链接,SYN(同步位)置位为1;此条报文也是对上一条对方发来的报文进行确认,所以ACK(确认位)也置位为1。
再来看下第三条,客户端给服务器回的
SIP 1.1.1.1 DIP 2.2.2.2
TCP
Sport x Dport 80
seq=m+1 ack=n+1
flag:ACK=1
- 这一条报文的seq(序列号) 是上一条报文的ack(确认号)。
- 这一条报文的ack(确认号)是上一条报文的seq(序列号)+1确认。
- 由于要确认上一条报文,ACK(确认位)置位为1;有由于已经请求过了TCP链接,所以SYN无需置位为1。
到此为止,TCP三次握手完成,成功建立链接。
在TCP三次握手第一次和第二次,ack(确认号)为上一条报文的seq(序列号)+1,并且+1确认只在三次握手中有。在第三次握手中seq(序列号)为上一条报文的ack确认号。
为什么是三次握手呢?两次不可靠,四次没必要。TCP是全双工的,就是通信允许数据在两个方向上同时传输。三次握手也可以比作
小姐姐,你愿意和我谈恋爱嘛?
愿意,那你呢?
我也愿意。( ^ _ ^ )
不是常说不清不楚的开始也会不明不白地结束吗,那么这三次对话(握手)就能够确定双方都有与对方谈恋爱(建立TCP链接)的意思,然后再开始正常的热恋(传输数据)。
传输数据
在三次握手的基础上进行数据传输。
SIP 1.1.1.1 DIP 2.2.2.2
TCP
Sport x Dport 80
seq=m+1 ack=n+1
flag:ACK=1
data=a(a为常数)
- 假设携带了a个数据。
那么服务器回的一条报文的ack(确认号)是多少呢?
SIP 2.2.2.2 DIP 1.1.1.1
TCP
Sport 80 Dport x
seq=n+1 ack=m+1+a
flag:ACK=1
- 我们要保证收到了对方的报文,要保证完整地收到了对方的报文。ack(确认号) 为m+1(上一条报文的序列号)+a(应用层字节数大小),这样才能确保收到了a个数据。这里不需要+1确认。
- seq(序列号)仍上一条报文的ack(确认号)。
- 此条报文也有确认性质,ACK(确认位)置位为1。
SIP 1.1.1.1 DIP 2.2.2.2
TCP
Sport x Dport 80
seq=m+1+a ack=n+1+0
flag:ACK=1
data=b(b为常数)
SIP 1.1.1.1 DIP 2.2.2.2
TCP
Sport x Dport 80
seq=m+1+a ack=n+1+0
flag:ACK=1
data=c(c为常数)
SIP 1.1.1.1 DIP 2.2.2.2
TCP
Sport x Dport 80
seq=m+1+a ack=n+1+0
flag:ACK=1
data=d(d为常数)
如果客户机给服务器一下发了三条报文,那么服务器回的报文的ack(确认号)又是多少呢?序列号+b,序列号+c,序列号+d,还是+b+c+d?
SIP 2.2.2.2 DIP 1.1.1.1
TCP
Sport 80 Dport x
seq=n+1+0
ack=m+1+a+b+c+d
flag:ACK=1
data=e(e为常数)
想一想,如果只是+b或+c等等,对方无法知道你是那一条报文没收全或是没收到,就会整个重传。
- 所以ack(确认号)是m+1+a(上一条报文的序列号)+b+c+d(应用层字节数大小)。
- ACK(确认位)仍然置位为1,TCP每条报文都在做确认,都具有确认性质。
这就是我们举例的一个传输数据的过程。 其中有一次客户机给服务器传了三条,那么万一服务器那个时候能够最大接收的TCP报文数是2呢,岂不是有一条丢失了?毕竟每次能接收的报文数也不是无线的。所以有一个TCP滑动窗口机制
TCP滑动窗口机制,通过TCP报文中的窗口字段来告知对方自身能够最大接收的TCP报文数,这样才能保证传输更有效率。
如果真的由于某些原因丢失了怎么办?这就有一个重传机制
TCP在发送数据时,会将数据同时放入重传队列,一旦收到回包,清空重传列队;一旦没收到,即使是丢了一个包也全部重传。
四次挥手
双方如何断开TCP链接呢?
SIP 1.1.1.1 DIP 2.2.2.2
TCP
Sport x Dport 80
seq=m+1+a+b+c+d
ack=n+1+e
flag:FIN=1 ACK=1
data=f(f为常数)
- seq(序列号)=m+1+a+b+c+d(上一条报文的确认号),没问题。
- ack(确认号)=n+1(上一条报文的序列号)+e(应用层字节数大小),没问题。
- FIN(终止位)置位为1,代表我要请求断开TCP链接.
- ACK(确认位)仍然置位为1。
SIP 2.2.2.2 DIP 1.1.1.1
TCP
Sport 80 Dport x
seq=n+1+e
ack=m+1+a+b+c+d+f+1
flag:ACK=1
SIP 2.2.2.2 DIP 1.1.1.1
TCP
Sport 80 Dport x
seq=n+1+e
ack=m+1+a+b+c+d+f+1
flag:ACK=1 FIN=1
- 这两条报文里第一条只有ACK(确认位)置位为1,意思是我收到了;第二条的ACK(确认位)和FIN(终止位)均置位为1,意思是可以断开TCP链接了。
- 他们的seq(序列号)为对方最后一条报文的ack(确认号)。
- 他们的ack(确认号)为对方最后一条报文的seq(序列号)+应用层字节数大小+1确认。
SIP 1.1.1.1 DIP 2.2.2.2
TCP
Sport x Dport 80
seq=m+1+a+b+c+d+f+1
ack=n+1+e+1
flag:ACK=1
OK,对方再次确认了。
断开TCP链接进行四次挥手,可以避免数据没有传完就断了的情况。
+1确认只在三次挥手和四次握手中进行。
以上就是本次的所有内容了。感谢大家的浏览,如有错误请指正,欢迎一起交流。