企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
## tcp的特点 这个大家基本都能说几句,面试的时候候选人也肯定会告诉你这些: * 三次握手 * 四次挥手 * 可靠连接 * 丢包重传 但是我只希望大家记住一个核心的:**tcp是可以可靠传输协议,它的所有特点都为这个可靠传输服务**。 ### [](http://jm.taobao.org/2017/06/08/20170608/#%E9%82%A3%E4%B9%88tcp%E6%98%AF%E6%80%8E%E4%B9%88%E6%A0%B7%E6%9D%A5%E4%BF%9D%E9%9A%9C%E5%8F%AF%E9%9D%A0%E4%BC%A0%E8%BE%93%E5%91%A2%EF%BC%9F "那么tcp是怎么样来保障可靠传输呢?")那么tcp是怎么样来保障可靠传输呢? tcp在传输过程中都有一个ack,接收方通过ack告诉发送方收到那些包了。这样发送方能知道有没有丢包,进而确定重传。 ### [](http://jm.taobao.org/2017/06/08/20170608/#tcp%E5%BB%BA%E8%BF%9E%E6%8E%A5%E7%9A%84%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B "tcp建连接的三次握手")tcp建连接的三次握手 来看一个java代码连接数据库的三次握手过程 [![image.png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/6d66dadecb72e11e3e5ab765c6c3ea2e.png)](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/6d66dadecb72e11e3e5ab765c6c3ea2e.png)image.png 三个红框表示建立连接的三次握手: * 第一步:client 发送 syn 到server 发起握手; * 第二步:server 收到 syn后回复syn+ack给client; * 第三步:client 收到syn+ack后,回复server一个ack表示收到了server的syn+ack(此时client的48287端口的连接已经是established) 握手的核心目的是告知对方seq(绿框是client的初始seq,蓝色框是server 的初始seq),对方回复ack(收到的seq+包的大小),这样发送端就知道有没有丢包了。 握手的次要目的是告知和协商一些信息,图中黄框。 **这就是tcp为什么要握手建立连接,就是为了解决tcp的可靠传输。** ### [](http://jm.taobao.org/2017/06/08/20170608/#tcp%E6%96%AD%E5%BC%80%E8%BF%9E%E6%8E%A5%E7%9A%84%E5%9B%9B%E6%AC%A1%E6%8C%A5%E6%89%8B "tcp断开连接的四次挥手")tcp断开连接的四次挥手 再来看java连上mysql后,执行了一个SQL: select sleep(2); 然后就断开了连接 [![image.png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/b6f4a952cdf8ffbb8f6e9434d1432e05.png)](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/b6f4a952cdf8ffbb8f6e9434d1432e05.png)image.png 四个红框表示断开连接的四次挥手: * 第一步: client主动发送fin包给server * 第二步: server回复ack(对应第一步fin包的ack)给client,表示server知道client要断开了 * 第三步: server发送fin包给client,表示server也可以断开了 * 第四部: client回复ack给server,表示既然双发都发送fin包表示断开,那么就真的断开吧 ### [](http://jm.taobao.org/2017/06/08/20170608/#%E4%B8%BA%E4%BB%80%E4%B9%88%E6%8F%A1%E6%89%8B%E4%B8%89%E6%AC%A1%E3%80%81%E6%8C%A5%E6%89%8B%E5%9B%9B%E6%AC%A1 "为什么握手三次、挥手四次")为什么握手三次、挥手四次 你再看三次握手的第二步发 syn+ack,如果拆分成两步先发ack再发syn完全也是可以的(效率略低),这样三次握手也变成四次握手了。 看起来挥手的时候多一次,主要是收到第一个fin包后单独回复了一个ack包,如果能回复fin+ack那么四次挥手也就变成三次了。 来看一个案例: [![image.png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/9db33f9304f8236b1ebcb215064bb2af.png)](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/9db33f9304f8236b1ebcb215064bb2af.png)image.png 图中第二个红框就是回复的fin+ack,这样四次挥手变成三次了(如果一个包就是一次的话)。 我的理解:之所以绝大数时候我们看到的都是四次挥手,是因为收到fin后,知道对方要关闭了,然后OS通知应用层要关闭啥的,这里应用层可能需要做些准备工作,有一些延时,所以先回ack,准备好了再发fin 。 握手过程没有这个准备过程所以可以立即发送syn+ack。 ### [](http://jm.taobao.org/2017/06/08/20170608/#ack-seq-len "ack=seq+len")ack=seq+len ack总是seq+len(包的大小),这样发送方明确知道server收到那些东西了。 但是特例是三次握手和四次挥手,虽然len都是0,但是syn和fin都要占用一个seq号,所以这里的ack都是seq+1。 [![image.png](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/45c6d36ce8b17a5c0442e66fce002ab4.png)](http://ata2-img.cn-hangzhou.img-pub.aliyun-inc.com/45c6d36ce8b17a5c0442e66fce002ab4.png)image.png 看图中左边红框里的len+seq就是接收方回复的ack的数字,表示这个包接收方收到了。然后下一个包的seq就是前一个包的len+seq,依次增加,一旦中间发出去的东西没有收到ack就是丢包了,过一段时间(或者其他方式)触发重传,保障了tcp传输的可靠性。