握手和挥手这辈子不再了
本文最后更新于:3 年前
本文主要内容是TCP协议的三次握手和四次挥手,就是我记了N遍,又忘了N遍的握手和挥手。
握手和挥手这辈子不再了
为啥要握手
答:确保数据能够到达目标
TCP协议
位于传输层,提供可靠的字节流服务
字节流:将数据块分割成报文
可靠:能够把数据准确可靠地传给对方。
怎样握手
第一次握手:
建立连接时,客户端发送syn包(syn=x)到服务器,并进入SYN_SENT状态,等待服务器确认;
SYN:同步序列编号(Synchronize Sequence Numbers)。
第二次握手:
服务器收到syn包,必须确认客户的SYN(ack=x+1),同时自己也发送一个SYN包(syn=y),即SYN+ACK包,此时服务器进入SYN_RECV状态;
第三次握手:
客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=y+1),此包发送完毕,客户端和服务器进入ESTABLISHED(TCP连接成功)状态,完成三次握手。
挥手说再见
挥手的过程:
第一次挥手:
Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
第二次挥手:
Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
第三次挥手:
Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
第四次挥手:
Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
为啥连接的时候是三次握手,关闭的时候却是四次握手?
答:因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭SOCKET,所以只能先回复一个ACK报文,告诉Client端,”你发的FIN报文我收到了”。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。
三次握手的夺命连环问(引用)
ISN代表什么?意义何在?
ISN,发送方的字节数据编号的原点,让对方生成一个合法的接收窗口。
ISN是固定不变的吗?
动态随机。
ISN为何要动态随机?
·增加安全性,为了避免被第三方猜测到,从而被第三方伪造的RST报文Reset。
·ISN动态随机使得每个tcp session的字节序列号没有重叠,如果出现tcp五元组冲突这种极小概率情况的发生,一个session的数据也不会被误认为是另一个session的。
第三方伪造RST报文,需要满足什么条件才能得逞?
需要sequence number 位于对方的合法接收窗口内。 而由于ISN是动态随机的,猜出对方合法接收窗口难度加大。
如果ISN = 0,那么猜出的难度就大大降低。
三次握手的第一次可以携带数据吗?为何?
不可以,三次握手还没有完成。
对方难道不可以将数据缓存下来,等握手成功再提交给应用程序?
这样会放大SYN FLOOD攻击。
如果攻击者伪造了成千上万的握手报文,携带了1K+ 字节的数据,而接收方会开辟大量的缓存来容纳这些巨大数据,内存会很容易耗尽,从而拒绝服务。
第三次可以携带数据吗?为何?
可以。
能够发出第三次握手报文的主机,肯定接收到第二次(服务器)握手报文,对吗?
因为伪造IP的主机是不会接收到第二次报文的。
所以,能够发出第三次握手报文的,应该是合法的用户。
尽管服务器侧的状态还没有“established”,接收到第三次握手的瞬间,状态就会切换为“established”,里面携带的数据按照正常流程走就好。
看到有人说,只看到过TCP状态位为 ’FIN +ACK’,但从来没有看过状态位只有 ‘FIN’,你应该怎样给他解释?
RFC793明确规定,除了第一个握手报文SYN除外,其它所有报文必须将ACK = 1。
很好,RFC规定的背后肯定有合理性的一面,能否深究一下原因?
TCP作为一个可靠传输协议,其可靠性就是依赖于收到对方的数据,ACK对方,这样对方就可以释放缓存的数据,因为对方确信数据已经被接收到了。
但TCP报文是在IP网络上传输,丢包是家常便饭,接收方要抓住一切的机会,把消息告诉发送方。最方便的方式就是,任何我方发送的TCP报文,都要捎带着ACK状态位。
ACK状态位单独能承担这个消息传递的任务吗?
不能!需要有 Acknowledge Number配合才行。
如果我方发出的Acknowledge Number == 10001,那意味着序列号10000及之前的字节已经成功接收。
如果对方占据字节序列号10000是应用层数据,那么就是确认应用层数据。
如果对方占据字节序列号10000是’FIN’状态位,那么就是确认接收到对方的’FIN’。
参考:
本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!