TCP协议详细总结
本篇文章详细解析TCP协议基础知识,包括三次握手,四次握手、报文分析以及设计到的网络编程等方面知识。
基本描述
TCP协议,中文名称:传输控制协议,是一种面向连接的、可靠的、基于字节流的传输层通信协议
面向连接的:在彼此交换数据前,需要建立一条连接,该连接建立完成后,会一直保持,知道该连接被主动或者被动超时断开。否则连接一直存在。
可靠的:当TCP发送一段数据之后,对端收到数据会返回确认,表示接收到了,如果没有收到确认,那么会将数据重传数次,并等待更长的时间。
基于字节流的:TCP发送的数据是基于8位字节表示的数据流
TCP连接的建立和终止
三次握手
建立连接过程可以通过举例子让大家更好的理解一下。销售员小明按照约定去客户家里向他推销自己的产品。小明首根据地址到客户家里,要想让客户开门,他第一步需要“核查楼牌号,开始敲门”,如果客户在家,听到有人敲门,打开门前需要问“哪位”,这个时候小明需要立即表明自己的身份说“您好,我是销售小明”,客户确定是小明之后,就会把门打开让他进去。这样连接就建立成功了,之后小明就开始跟客户介绍他所推荐的产品。
TCP建立连接过程,大家通常称为三次握手,完成三次握手之后,则TCP连接就建立完成,如下图为三次握手简图,小明就是客户端,客户就是服务器。
通过以上图片我们结合打电话的例子去分析TCP建立连接这个过程:
第一步:小明(客户端)想给客户介绍产品,他确认地址,开始敲门这个过程就是客户端发送SYN请求这个流程;
第二步:客户听到敲门声,问清楚身份“您好,你谁谁”,就是服务器端接收到客户端发送SYN请求建立连接报文后,主动回复SYN,ACK报文;
第三步:小明听到客户说话后,立即说“您好,我是销售小明”,就是客户端完成连接最后一步,发送ACK报文确认。
这样,小明就进入客户家里向他介绍自己的产品。
这个过程中,中间有任何一个环节出现错误,该连接都无法建立成功,小明敲门、客户没在家,没有回复任何信息、以及小明听到客户回复时,没有表明自己的身份。
三次握手阶段,TCP协议端口会处在不同状态,
LISTENING:服务出去监听状态,监听客户端发送连接请求,即等待被连接
SYN-SEND:客户端调用connect,发送SYN报文后,未收到ACK回复报文
SYN-RECV::服务端收到客户端SYN建立连接请求报文,会主动回复SYN,ACK报文,服务器等待客户段回复ACK确认报文。
ESTABISHED:表示连接建立成功状态
四次挥手
TCP连接终止过程我们通常称为四次挥手,那么为什么断开连接时会需要四个阶段呢?我们也可以结合身边的例子去理解。可以通过老师下课的场景。
下课铃声响起,老师还在给同学上课,当老师把本节课的内容都讲完之后,说“同学们,本节课就到这,大家没有问题我就走了”,同学回复“老师再见”,但是这个时候,同学小王还有一些问题需要请教老师,就站起来说“老师,我有一些问题”请教一下,这个时候老师还没有走,他需要解答同学的问题,当小王同学没有问题的时候,就会跟老师说“老师,我们没有问题了,您可以走了”,这个时候老师说“好的”,之后才会离开课堂,结束本堂课程。
我们通过上面图片结合我们的例子去分析四次挥手的各个阶段
第一步:老师表明自己的课程已经讲完了,可以准备下课了。
第二步:同学回复老师“老师再见”,但是小王还有问题需要请假,所以他叫住老师,把他的问题跟老师讨论。这个时候老师还是没有离开课堂。
第三步:小王问题都解决完成后,主动告诉老师,自己已经没有问题了,老师可以走了。
第四步:老师确定小王没有问题之后,才会离开课堂。
为什么会需要四个阶段呢?主要原因是因为当一方主动断开连接时,不能保证对方所有数据都发送完成,这个时候处于半关闭,如果对方还有数据没有发送完成,仍需要对数据处理,需要等待对方所有数据发送完成后,并主动发送断开请求后,才可以完全终止连接。
同样的,终止连接TCP也会处于不同的状态
FIN-WAIT1:程序调用close函数,主动发送FIN断开连接报文后,在收到对方回复ACK确认报文前,处于该状态。
FIN-WAIT2:收到对方回去确认ACK报文后,出去该状态,保持到对法发送FIN,ACK主动退出请求报文前。
TIME-WAIT:收到对方发送FIN,ACK关闭请求报文,回复对刚ACK确认报文后,处于该状态,该状态会保持2MSL,防止对方请求重传。
CLOSE-WAIT:被动收到FIN断开连接请求,回复ACK报文后进入该状态,一直保持到本端主动发送FIN,ACK断开连接请求,之后进入LAST-ACK状态
LAST_ACK:本端发送FIN,ACK断开连接请求后,接收到对方确认报文ACK前处于该状态
CLOSED:由TIME-WAIT状态等待2MSL时间后或者处于LAST-ACK状态受到对方ACK确认报文之后,会进入CLOSED状态。
TCP报文分析
报文是TCP协议完成报文,结合这个报文可以简单对seq、以及ack的值讲解一下。
seq这个值表示的是本报文数据开始的位置,因为TCP是基于字节流,可以把所有需要发送的数据看成一条很长很长的字符串,因为每次传输的报文内容会分片,不可能一次把所有报文都发到目标,而且还会出现报文丢失问题,这个时候就需要在报文中标识本条报文开始的位置,也就是字符串的下标位置,这样对方收到报文后就可以将报文分片进行重组。
ack这个值表示的是收到对方多少报文,这个值从开始就累加,用来确认我确实收到了这些报文,方便对方清理发送缓冲区。