共计 3486 个字符,预计需要花费 9 分钟才能阅读完成。
新人拜访
“您好,我是 TCP
服务的实习生,刚培训完,请问您就是 TCP
老司机吗?”
正坐在办公室悠闲喝着咖啡的我,差点一口喷出来,“哦哦,行,你终于来啦,看来几天前的资源申请通过了啊,老司机?”
“浏览器老大这么叫你的,说你厉害,靠谱的很。”
“好吧,既然来了,赶紧准备准备!这你的工作台。”我放下手中的咖啡,走到了一个靠窗的工作台,指了指。
“好嘞。”说着,刚来的小伙子走了过来。
工作台
“好多工具啊,这个通道是什么,这儿还有个钟?都怎么用呀?”小伙子满脸好奇的问道。
“这样吧,从左到右,我一一给你说说。”
“首先,最左边呢,是个通道,这里会蹦出应用层需要我们发送的数据。最常见的就是 HTTP
那小子的报文了。”
“了解,我们的工作就是发送应用层的数据。原来不需要我们自己去拿啊!”
“旁边呢就是扫描机,你需要根据实际情况把数据进行扫描,扫描机会把数据分块,按序号,放在旁边这个盒子里。”
“嗯嗯,这个我清楚,数据块大小需要根据实时的网络情况确定。”
“不错。这小伙子脑子还挺灵光。看来培训的不错”我心中暗暗赞到。
“再往右,你看到这又是一个通道,这个通道就是我们和服务器进行沟通的通道了。通道旁是两个计数器,分别用来记录我们的序号和服务器序号,这个会自动加,你不用操作。就叫 1
号计数器和 2
号计数器吧,等下会用到。”
“好的,1
号计数器其实就是报文中的序号?”
“嗯嗯,不错,用的时候看一眼就行,在计数器旁边有几个按钮,我给你说说。这里最好记一下。”
“嗯嗯”说着小伙子拿出了笔记本开始记录。
任务降临
我指了指标着 SYN
的按钮,说道:“这个是请求连接按钮,也就是通知服务器,我们想发数据给他。”
说着,最左侧的通道突然一闪,蹦出了一个 HTTP
服务打包好的包裹,刚来的小兄弟显的有点慌乱,咽了一口气。
“刚好,那我就那这给给你做一下演示吧。”说着,我站到了工作台正中。
“嗯。”小兄弟紧张的说不出话来。
“首先呢,按一下 SYN
按钮,请求发送数据。”1
号计数器跳了一下,由原本的 0
跳到了 1
。“按下这个按钮工作台会发送一个请求连接报文,相信报文的内容你应该清楚吧?”我问道。
“SYN
为 1
,序号为 0
。”看了一眼 1
号计数器,小伙子自信的答道。
“嗯,不错!”不一会计数器旁的通道蹦出了一段报文,2
号计数器直接由 0
跳到了 11
。
“让我们来看看,都有什么,你看这里。”我指了指报文中的 ACK
,小伙子也靠了过来。
“ACK
等于 1
,说明服务器接受了我们的连接请求,对吧?”小伙子说道。
“是的,那我们建立连接?”我露出了狡猾的笑容。
“还需要核对 确认序号
吧?”小伙子有点困惑。
“为什么?”我反问道。
“确保连接的准确性。老师说过,网络是一个复杂的环境,会出现报文滞留的情况,因此 TCP
连接两端规定,在得到请求连接时,需要将 确认序号
置为请求序号加 1
。那么现在我们应该还要核对 确认序号
与 1
号计数器的值!”小伙子转眼看向 1
号计数器,“咦,怎么一样?应该是差 1
的啊?”
“你忘了,在你按下 SYN
按钮时,1
号计数器已经跳了一下吗?”
“哦 ~”小伙子恍然大悟,“那是应该相等,这个也太好用了吧!得记一下!”
“唰唰唰”一旁发出铅笔摩擦纸面的声响,“有我刚来的样子”我不经感叹道。
“接着,你看 SYN
字段为 1
,说明服务器请求连接,TCP
是一个稳定的连接,双向数据的通道,需要双方都确认连接状态,这点我不需要特殊说明吧?”
“嗯嗯,在学校老师说过。”
“那好,为了确保连接的正确性,我们需要和服务器做相同的操作,把序号加 1
后,放在确认序号内,服务器返回的序号是 10
我们返回 11
就行。但这些不需要你进行实际的报文生成,在你确定可以建立连接的情况下,按一下标着 ACK
按钮就行。”说着我按下了 ACK
按钮。“现在三次握手结束,连接通道成功生成。我们开始传输数据,剩下还有几个按钮用到的时候在说。”
“那个,我想问一下,我知道 TCP
是个双向数据通道,但如果我们不确认建立连接,直接发送数据应该也没问题吧?我们和服务器都已经发送了一次请求,并且都收到了,为什么还要确认一下呢?”小伙子若有所思道。
“既然是双向数据通道,那么通道的两端都应该清楚自己和对方的发送和接收的能力,对吧?”
“当然!不然通道是不稳定的。”
“那你想想,在前两次通信过程中,双方都知道了哪些情况?”
“第一次我们发报文,第二次服务器返回报文我们接收到,那我们就知道了我们有能力发送和接收,服务器也有能力接收和发送。”
“那服务器呢?”
“服务器的话,应该知道了他自己有能力接收,知道我们有能力发送,他自己却不清楚他能不能发送,也不知道我们是否能接收!因为我们还没回复他。”
“因此呢,三次通信(握手)让双方都知道了双方都有发送与接收的能力,这对于一个双向数据通道来说至关重要。”我解释道。
“嗯嗯,我记一下。”又是一阵“唰唰唰”的声音。
发送报文
“已经建立了通道,那接下来就简单了。”我拿起 HTTP
扔过来的数据,说道:“我们看看我们一次能发送的数据包大小,在这儿。”我指了指工作台最右侧的屏幕,屏幕上显示着一连串的信息,“这些就是系统参数,这个就是我们网络所能承受的最大发送量。”
“嗯,一次可以发送 1100
字节。”小伙子边看边说道。
“嗯,不错。那我们就将数据按 1000
来切割吧,剩一定空间个报文头部使用。”说着我启动一遍的扫描机,设定为 1000
,丢进 HTTP
的数据,一旁的盒子出现排好序的数据块。
“好神奇啊,学校里都我们自己切的。”小伙子双眼中冒着金光。
“接下来发生报文就好了。”
“好的,我来拼接数据,源端口:5800
,目标端口:80
,序号:1
,数据偏移:20
,标志位:无特殊情况,窗口大小:3
,校验和:…”小伙子突然叽里咕噜一堆,吓了我一跳。
“不需要这么麻烦,源端口,目标端口,在工作台接收到应用层数据后,就能生成,至于序号和偏移量,你也不用关心啦,我来演示一遍,看好。”
我瞧了一眼服务器先前返回的报文,得知窗口为 3
,拿起盒子里的数据就往按钮旁的通道里丢,一连丢了 3
个。1
号计数器也连续跳了 3
下,由 1
跳到了 1001
,在由 1001
跳到了 2001
,最终定格在 3001
。
“好了,接下来就等服务器响应了。”
“这就好了?”小伙子明显有点不敢相信。
“对啊,好了!等服务器确认就行。”我有点得意。“工作台会帮我们把数据打包生成报文,这个工作台可是我的专利!”
“哇塞,老司机就是厉害!比学校里高级多了。”小伙子双眼中再次亮起金光。
单向关闭
没过多久,2
号计数器连跳 3
次,哒哒哒,通道里蹦出 3
个服务器返回的报文,内容都为:请求完成,需要下一份数据。
我拿起盒子里的下 3
块,往通道里扔。1
号计数器哒哒哒,又连着跳了 3
次。如此循环往复了十几次,数据终于发完。
“今天的网不错诶,没有重发的情况出现。现在我们发完了,只需要等待服务器发送数据就行了。”
大概过了 10ms
,通道内陆陆续续开始蹦出报文,我刚想上手,一旁小伙子一把把报文揽走,“这个我熟,我来吧!”
获取报文数据,按照序号排好,一顿操作还挺溜。
哒哒哒,2
号计数器不断的跳动,定格在 50001
上。
“好现在数据也接收完毕了,需要进行单向关闭。如何进行关闭?”我想考考小伙子的能力。
“发送报文,将 FIN
置为 1
,序号为 43001
。”小伙子瞧了一眼 1
号计数器说道:“然后等服务器返回确认就好了,哦,对为了应付网络滞留情况出现,需要核对 确认序号
。”
“不错,但在这 …”我话还没说完,小伙子兴奋的说道:“是不是按那个 FIN
按钮就好了?”
“嗯,对!我们只需要核对 确认序号
就好了。你来操作吧 ~”看着一脸兴奋的小伙子,我停止了手中的操作。
“好的。”说着,小伙子按下了 FIN
按钮。1
号计数器跳了一下,定格在 43002
。不一会通道里蹦出了报文,确认序号与 1
好计数器一致,都为 43002
。
“现在单向关闭成功,等待服务器请求关闭。”小伙子一副训练有素的样子。
“嗯,不错,接下来就等待服务器最终确定关闭了。”我拿起一旁的咖啡,慢悠悠的说道:“那你知道为什么这是单向关闭?”
“因为只有我们这边确认把数据都已经发送完毕啦 ~ 没准服务器还有数据给我们呢 ~”
“嗯,不错。”我拿起咖啡喝了一口,不经感慨道:“后继有人了啊!”
“老大,服务器发出关闭请求了,你看。”小伙子拿起一个报文,对我说道。
“我想你应该知道怎么做了吧?”
“嗯嗯,按 ACK
按钮就好了,这个和开启连接确认是同一个操作,按您的智慧,应该是这样。”说着按下了 ACK
按钮。
“嗯,这个彩虹屁真香,哦不,你真聪明!”
“哈哈”我们同时发出笑声,“我和你说,那个 HTTP
服务部可不咋的,经常砸我,这不数据都好了,砸 TM
的。”
“duang
~”通道一头发出一阵巨响,“TCP
你们没完了是不?”