前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >了解这个TCP,你也能涨薪3K!

了解这个TCP,你也能涨薪3K!

作者头像
三哥
发布2020-01-17 10:55:02
4730
发布2020-01-17 10:55:02
举报
文章被收录于专栏:java工会

写在前面

◆ ◆ ◆ ◆

有一次去浦东的一家互联网公司面试java后端开发。当天下午聊了技术、部门经理、HR,然后让回去等通知。当天晚上HR打电话过来聊薪资,巴拉巴拉说了一堆什么公司制度啦,这个年限只能匹配这个薪资,给的薪水比预先的低了2K,于是也直接跟HR说了达不到预期,不想考虑。

过了三天HR说要不再来公司试一下,公司来了个从阿里挖来的CTO,聊得好了说不定可以提薪。于是又去面试了一下,java基础,Spring框架,JVM,优化,项目问了一堆,情况还行。

最后他问了一个开放性问题,说让我思考十分钟,然后再回答。但是小明同学立马就回答了。回答结束了,他把HR叫进来,说了一句“在原先给他的薪资基础上再涨3K……”

最后,小明同学也就入职了这家公司……

问题

◆ ◆ ◆ ◆

题目是:想象在一条宽阔的大河两边有两支军队,河中心有一个岛屿,上面有一群反贼。两支军队只有在同时进攻,才能拿下反贼。但是军队都没有任何交流方式,只能派士兵去对面报信。士兵过河一定要经过岛屿,可能就会被杀死。要如何保证两支军队能够同时进攻岛屿?

分析

◆ ◆ ◆ ◆

经过分析,其实就是一个可靠消息传递的问题。两端需要及时通信,并且保证可靠传输。士兵过河被杀死的过程,可以理解为数据丢失过程。要保证两端建立可靠消传输……这不就是TCP三次握手嘛!

连接三次握手

◆ ◆ ◆ ◆

在TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接: 第一次握手:建立连接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;(SYN:同步序列编号) 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态; 第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手;

完成三次握手,客户端与服务器开始传送数据;

在此期间,若规定时间内没有收到回复,则重新发送数据包。

过程如下图:

断开四次挥手

◆ ◆ ◆ ◆

由于TCP连接时全双工的,因此,每个方向都必须要单独进行关闭,这一原则是当一方完成数据发送任务后,发送一个FIN来终止这一方向的连接,收到一个FIN只是意味着这一方向上没有数据流动了,即不会再收到数据了,但是在这个TCP连接上仍然能够发送数据,直到这一方向也发送了FIN。首先进行关闭的一方将执行主动关闭,而另一方则执行被动关闭:

第一次挥手: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状态,完成四次挥手。

简单的理解为:

1、C说:我数据发完了,要准备断开啦 2、S说:行,我知道你发完了 3、S说:数据我收完了,可以断开了 4、C说:好的,断开连接

实际中还会出现同时发起主动关闭的情况,如下图:

关注点

◆ ◆ ◆ ◆

以上只是基本原理,另外还有一些关注点,也要注意下:

  1. 为什么连接时三次,而断开时是四次?

因为当Server端收到Client端的SYN连接请求报文后,可以直接发送SYN+ACK报文。其中ACK报文是用来应答的,SYN报文是用来同步的。但是关闭连接时,当Server端收到FIN报文时,很可能并不会立即关闭Socket,所以只能先回复一个ACK报文,告诉Client端,"你发的FIN报文我收到了"。只有等到我Server端所有的报文都发送完了,我才能发送FIN报文,因此不能一起发送。故需要四步握手。

2.为什么不能用两次握手进行连接?

三次握手完成两个重要的功能,既要双方做好发送数据的准备工作(双方都知道彼此已准备好),也要允许双方就初始序列号进行协商,这个序列号在握手过程中被发送和确认。

现在把三次握手改成仅需要两次握手,死锁是可能发生的。作为例子,考虑计算机S和C之间的通信,假定C给S发送一个连接请求分组,S收到了这个分组,并发送了确认应答分组。按照两次握手的协定,S认为连接已经成功地建立了,可以开始发送数据分组。可是,S的应答分组在传输中被丢失的情况下,将不知道S 是否已准备好,不知道S建立什么样的序列号,C甚至怀疑S是否收到自己的连接请求分组。在这种情况下,C认为连接还未建立成功,将忽略S发来的任何数据分组,只等待连接确认应答分组。而S在发出的分组超时后,重复发送同样的分组。这样就形成了死锁。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-01-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 java工会 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档