- 深入理解tcp
- seq位增长规律
- ack位的增长规律
- 其它三位
- 剖析三次握手
- 剖析四次挥手
- tcp有限状态机
+======================================================================
张贺,多年互联网行业工作经验,担任过网络工程师、系统集成工程师、LINUX系统运维工程师
笔者微信:zhanghe15069028807,现居济南历下区
+======================================================================
深入理解tcp
无论是程序员、网络工程师、还是运维人员在面试的时候总是会问到有关于tcp连接问题,我们这一章就来好好的研究一下。虽然我是学网络出身,并且已经毕业好几年了,但是我对tcp连接总是理解的不通透,今天就趁写这篇博文的机会好好的梳理一下。
NOTE:无论别人讲的再好,如果你不亲身验证的话,终究是学的不通透。
环境说明:
客户端ip | 192.168.80.99 |
---|---|
服务器ip | 192.168.80.134 |
seq位增长规律
seq是什么?
seq是数据段的序号。
为什么要有seq序号?
有的数据包过大,要在传输层拆分成多个包,第个包都要有序号,这样再组合起来的时候有依可循。tcp提供有序传输,所以每个数据段都要标上一个序号。
它的起始值我们没有必要知道是如何计算出来的 ,但是我们要理解它的增涨规律,如下图,列出了一段数据报文,我们来分析其中的规律。
seq序号=上一包的序号+长度
如下图所示,第一包的序号是317,长度是0,可以推断出其发送的下一包的序号是317+0=317,通过第3个包可以验证。
NOTE:以上规律不适合分析三次握手。
ack位的增长规律
确认号表示接收方通知发送方确认已经收到了哪些字节。
比如甲给乙方发送了:”seq=x,len=y“,那么乙方要回复的ack位的值就应该是x+y,表示它收到了x+y之前的所有字节。
我们将seq的增长规律和ack的规律整合一下,模拟几个交互:
客户端:seq=100,len=5,ack=0
服务端:seq=200,len=10,ack=105(客户端的seq+len)
客户端:seq=105,len=8,ack=210(服务端的seq+len)
服务端:seq=210,len=15,ack=113(客户端的seq+len)
也就是说对方的ack就等于自己将要发送的seq号。
NOTE:以上规律不适合分析三次握手。
其它三位
SYN:携带这个标志位表示要发起连接请求,因为连接是双向的,所以双方在建立连接时都要发,这就是tcp握手的前两次握手。
FIN:携带这个标志位表示请求终止连接,所以双方在关半连接时都要发,这就是四次挥手的前两次挥手。
RST:用于重置一个混乱的连接或拒绝一个无效的连接,比如你连接linux并没有开放的端口时,linux就会回复你RST.
剖析三次握手
下图是我通过wireshark截取的三次握手过程:
解释一下:
-
客户端:我想给你建立连接,我的初始序号是x,如果你同意的话,就在你的应答位上(ack位,把我的序号+1)上图我们看到初始序号是0,但实际上并不是0,而是wireshark显示成0了。
-
服务器:我也想跟你连接(SYN),Ack=X+1 ,我的序号是Y,如果你同意就在你的应答位上(ack位,把我的序号+1)
-
客户端:当然同意了(Ack=Y+1)
体现为:
-
客户端:SYN seq=X
-
服务端:SYN seq=Y Ack=X+1
-
客户端:seq=X+1 Ack=Y+1
为什么要用三个包来建立连接呢?两个不行吗?其实是可以的,只是不太可靠。
假设客户端在第一次建立握手时数据包在半路阻塞了,客户端维护一个超时时间,时间到了就认为这个包已经丢了,于是又重新发送一个请求连接包,这个包很快到达了服务器建立好通道之后传递完数据之后紧接着把连接就给关闭了。但之前阻塞那个数据又来到了服务端,服务器并不知道这是一个无效的请求,所以按照惯例,服务器又回复了,回复给客户端,但客户端这时的套接字已经关闭了,对于这个报文已经不认识了,就丢掉,服务器要等到超时才能关闭这个连接,这样比较浪费服务端的资源,同时也给客户端增长开销。
但现在有了三次握手,服务端收到了那个过期包,所以按照惯例,服务器又回复了,回复给客户端,而客户端一看这个包已经过期了,于是就回复一个拒绝包,干脆利落的拒绝,服务器立马就把维护套接字关闭掉,做别的事情去了。
三次握手比两个握手就多了一次回复,这一次回复是比较重要的,就像一个男生追一个女生,如果女生不拒绝,也不同意,就浪费了男生太多精力,让男生猜不透女生的心思。假如说女生明确给一个回复,同意就同意,不同意就拉倒,这样男生也死心了,也能抓紧去追别的女生。
剖析四次挥手
-
客户端:请求断开连接,FIN和ACK都置位
-
服务器:知道了,ACK置位
-
服务器:我这边也想断开了,FIN和ACK都置位
-
客户端:知道了,断开吧,ACK置位
以上标准的上次挥手过程,但真实的情况下,有时候也是三次挥手,如下所示:
第一步:客户端请求断开连接,
第二步:服务器直接就将第二步和第三步合到一个包里面
第三步:客户端回复一个同意,就完事了!
可见,理论和现实还是有差别的。