刚刚学完这个知识,感觉很重要,在此记录下来,参考资料,《计算机网络》 谢希仁 第六版
TCP报文格式
注意:在理解三次握手之前必须理解首部中的这几个字段的含义
首部的重要字段
序号(seq):TCP连接中传送的字节流中的每一个字节都按顺序编号,首部中的序号字段的意思是本报文段所发送的数据的第一个字节的编号
确认号(ack):期望收到对方下一个报文段的第一个数据字节的编号,也就是说确认号与发送方下一次发送过来的报文段的序号(seq)相等。
若确认号是N,则表示我方已正确收到了N-1为止的所有数据。
确认(ACK):仅当ACK为1的时候确认号(ack)才有效,由于连接建立后就要发送数据,所以连接建立后传输的所有报文段ACK都要为1。
同步号(SYN):SYN=1,ACK=0表示这是一个请求连接的报文段,
SYN=1,ACK=1表示这是一个同意连接的报文段。
终止(FIN):FIN=1时,表示此报文段的发送方的数据已发送完成,要求释放连接。
三次握手
大白话:
1.A对B说,我想和你连(SYN=1,ACK=0),我要是发送数据了就从x+1开始(seq=x,TCP规定SYN=1的报文段不携带数据,但是要消耗掉一个序号)
2.B对A说,可以啊(SYN=1,ACK=1),我要是接收你的数据就从x+1开始收吧(ack=x+1),我发送数据的话,从y+1开始(seq=y,此处同上不携带数据,消耗掉一个序号)
3.A对B说,我知道你同意了,我要是接收你的数据就从y+1开始收(ack=y+1)。
TCP规定,ACK=1的报文段可以携带数据,但是如果不携带数据则不消耗序号。
此处没有携带数据,所以下一次A发送数据还是从x+1开始的(seq=x+1)
此时连接就建立了。
为什么要使用三次握手呢?两次为什么不行呢?
这主要是为了防止已失效的连接请求报文段又突然传到了B,进而产生错误。
我们假设使用两次握手,即A向B请求连接,B向A发送同意连接的报文后,连接建立。
有一种情况,A向B发送了请求连接,但是这个请求在网络中间堵车了,A见B迟迟不回答,就再次发送了一个请求,
第二次请求,B直接收到了,返回一个同意连接这个连接就建立了。之后传输,结束,释放,完事。
但是还没完,过了很久,第一个堵车的请求才到了B,B向A发送了同意连接后就等待A的数据了,但是A此时并没有连接
的要求,就直接将同意连接的报文丢弃了,B要等很久才知道A根本就没连,它的许多资源都白白浪费了。
如果采用三次握手,B要是没有收到A的确认(B等待确认的时间要短的多),就知道A并没有连接,B就会放弃。
四次握手
依旧大白话:
1.A对B说,我传给你的最后一个数据是u-1(seq=u),我发完了,现在想走了(FIN=1),你回个话。(FIN报文段即使不携带数据,也要消耗一个序号)
2.B对A说,你传给我的最后一个数据是u-1(ack=u+1,之前的报文段消耗了一个序号),我下一步要发送的数据是从v开始的(seq=v)。
你发送完了,可是我没有发送完啊,等着让我发完!然后B就开始把剩下的数据给A。(如果B还有数据要给A的话)
3.B的剩余数据发送完之后,就对A说,我发送给你的最后一个数据的序号是w-1(seq=w),你传给我的最后一个数据是u-1(ack=u+1),
现在我的数据也发完了,我想走了(FIN=1)。
4.A说我给你的最后一个数据是u-1(seq=u+1),我收到你的最后一个数据是w-1(ack=w+1,FIN报文要消耗掉一个序号),你可以走了。
之后B的连接就完全关闭了,但是A的连接要等2MSL个时间才会完全关闭。
为什么?
看课本去吧~
至于为什么选择使用四次握手,我认为原因是
A单方面提出的分手,是因为它已经将数据传送完成了,因此向B提出分手(第一次握手)
B事先不知道A要提出分手,所以它要将善后工作处理好,将剩余的数据发给A, 通知A等一下(第二次握手)
中间可能经历很多B向A的数据传输
B将善后工作处理完了,要通知A一下,让A知道B的数据已经发完了(第三次握手)
A要通知B,我知道你将数据发完了,你可以走了(第四次握手)
B是个好人。/(ㄒoㄒ)/~~
为了照顾新手,我屏蔽了很多细节和其它知识点,要想详细了解TCP的工作原理,要仔细阅读相关书籍。
您的批评指正是我最大的动力,希望各位看官发现错误后及时给我留言,在下感激不尽...