内容简介:经常在前端的面试群中发现有人会碰到面试官去询问tcp的握手和挥手问题,诸如你了解tcp吗,解释一下tcp的三次握手和四次挥手,我认为如果只是简单的了解这2个问题,真的那么有意义吗?所以,不防试着去多了解一点网络通信的内容,记得在上家公司的时候有个老哥说过,网络通信其实还是蛮重要的,毕竟我们现在无论是工作还是生活基本都处于互联网之中,尤其作为开发者基本上每天都在和http请求打交道,so 了解网络传输的原理还是有必要的,下面我们稍微深入的来看下网络传输的内容。OSI(Open Systems Interco
经常在前端的面试群中发现有人会碰到面试官去询问tcp的握手和挥手问题,诸如你了解tcp吗,解释一下tcp的三次握手和四次挥手,我认为如果只是简单的了解这2个问题,真的那么有意义吗?所以,不防试着去多了解一点网络通信的内容,记得在上家公司的时候有个老哥说过,网络通信其实还是蛮重要的,毕竟我们现在无论是工作还是生活基本都处于互联网之中,尤其作为开发者基本上每天都在和http请求打交道,so 了解网络传输的原理还是有必要的,下面我们稍微深入的来看下网络传输的内容。
base
OSI(Open Systems Interconncection,开放系统互联)网络分层
从上到下分别是:
7.应用层(Application)
6.表示层(Presentation)
5.会话层(Session)
4.传输层(Transport)
3.网络层(Network) -- 路由器
2.数据链路层(Data Link) -- 交换机
1.物理层(Physical) -- 网卡、集线器(Hub)
基础内容不做过多的讲解,有需要的可以出门右转 ok 我们今天主要关注的是tcp层的内容,下面的内容,如果有兴趣建议大家按照步骤实际操作去看看,首先介绍一个工具wireshark,这个 工具 可以帮助我们抓到tcp以及更底层的包,下载到这里,打开后有个download,下载自己系统能用的就好,一路安装到全部完成,接下来我们开始一次实战抓包。
抓包
我这里利用了百度的首页做了一次抓包实验,首先要设置一个过滤
你可以选择http 和 tcp 或者 tcp only
然后到控制台中去ping 一下百度首页的ip
ok 看到ip是180.97.33.108
然后我们到wireshark中设置一下查询的ip
到chrome中打开百度的首页,然后就能看到tcp的传输信息了
内容有点多,我们通过这个内容来观察一下tcp的传输过程
tcp base
先看下tcp的头部报文结构 1.tcp协议层是不关心ip的,具体ip的定位是由ip层来决定的,但是tcp层需要确定端口号,所以他会携带source 和 destination的port信息,以便能找到对应的端口号;
2.sequence number 实际中使用的SEQ,也就是序号,这个序号起了很重要的作用,我们都知道tcp和udp最大的区别在于tcp是稳定并且有序的,其中seq就可以保证有序,当A向B发送一个数据包的时候,seq会叠加,每一个传输方在传送数据的时候都会带上这个信息,另一端能按照这个序号来 排序 收到信息的顺序,从未保证了信息的传递是有序的,也能通过它来确认有没有出现丢包的情况;另外要注意的是当有数据需要发送的时候,seq会随该序列号为原点,对自己将要发送的每个字节的数据进行编号,比如当前seq = 10,本次要发送的数据包大小是200字节,那么实际发送的时候会更新seq=210,以便保证传输的数据的顺序;
3.acknowledge number,实际中使用的ACK,是另一端对对方seq的一个回应,一般会把对方给的seq+1然后下一次发包的时候带上,这样的话对方就知道我们是收到前面的消息的;
4.windown代表的是滑动窗口,实际中用win来表示,win的大小很重要,win越大的传输越快,因为win的大小直接决定了某一端一次可以同时发送多少个数据包,而不用等待对方的应答ACK回来,但是win会随着每一个数据包的发送而变小(稍后解释);
5.reserved 是tcp传输很重要的角色,标志位,响应方会根据对方给的信号执行对应的操作,比如执行断开连接的时候一般都是使用FIN标志位;
基础内容不做过多介绍,不懂的可以移步这里先看下概念,后面我们会结合实际来介绍
三次握手(敲黑板)
观察前几次传输,TLS类型的我们可以先忽略,它是处理ssl加密的内容,有兴趣的可以自己去google,重点看前三次的tcp,第一次是我们自己的ip向百度的服务器ip发了第一个包,seq=0,起始的数据信号是0,win=65535代表我这边的窗口大小是65535,len=0代表我这边希望接受的包的大小长度是0,mss代表我这边本次传输能接收的最大包的内容是1460(其余的我们暂时不用关心)。下面我们模拟一下对话内容:
A:B,你好,我是A 请求建立连接,我的seq是0,我的win是65535,我希望本次回应我的内容长度len为0,我本次能接收的最大内容是1460,over; B:A,你也好,收到你的信息了,我是B,我本次的seq是0(注意,双方的序号是独立计算的,这里都从0开始的),我回应你的ack是1(A的seq+1,代表我收到你seq是0的消息了),我的窗口大小是8192,我希望你回应我本次消息的len也是0,我这边能接收的最大回应大小是1452,over; A:好的,我收到你的回应了,我现在给你发送的seq是1(上一次是0,这次是1),我回应你的ack是1(B的seq+1),我当前的窗口大小是25984,我希望的回应长度是0;我们建立好连接了,over;
到这里,完整的三次握手就结束了,后面就可以执行别的数据传输了,到这里,不知道有没有想过,为什么确定一次连接需要三次握手,不是1次,也不是2次,也不是4次,
首先,1次肯定不行,1次的话 一方无法确认另一方的情况,所以最少都是2次起步,
2次:
A:喂喂喂,我是A,你听的到吗? B:在在在,我能听到,我是B,你能听到我吗? A:(听到了,老子不想理你) B:喂喂喂?听不听到?我X,对面死了,我挂了。。
4次:
A:喂喂喂,我是A,你听的到吗? B:在在在,我能听到,我是B,你能听到我吗? A:听到了,你呢?你能听到吗? B:??你是智障?我不是说了我能听到吗,不想跟xx说话。。。
所以最合理的还是3次:
A:喂喂喂,我是A,你听的到吗? B:在在在,我能听到,我是B,你能听到我吗? A:听到了。我们今天去钓鱼吧。。balabala
so,就是这样,其实不是不能更多,但是可靠的同时,还要考虑性能和时间问题,所以,目前公认的握手次数还是三次比较合理。
四次挥手
我们知道tcp的连接是全双工的,A和B是可以互相通信的,不理解的话,可以想想打电话(类比,不要当真),打电话的场景就是单双工的,因为同一时间只能一个人说话,另一个人听,如果2个人一起说话,那谁都听不清楚了,没有意义,但是tcp是全双工的,就是A 正在给 B发信息的同时,B也在给A发信息,所以当断开的时候,必须要求双方都得知道,如果只有一方知道,肯定不行,因此,断开的时候,就需要下面这样:
A:B,不好意思,我这边需要关闭连接了,你准备一下?(发了一个fin信号给B,等待回应)
B:好的A,我收到你的关闭信号了,我还有数据没发好,你等我下(回应A,带回去ACK的最后一个信息,失败可以重发)
B:A老弟,我好了,我可以关闭了,给你最后说一下,等下你回应我的话,我就直接关了;
A:好的老哥,我回应你一下,你收到就关闭吧,不用理我(发完这条信息后,进入time_wait状态)
B:(收到ack信息,直接就关闭了),此过程不产生数据的交互,不算挥手次数
A:等待2MSL(最大报文段生存时间)后,B没东西给过来,我也关了;
到这里4次挥手就结束了,2个问题:
1.为什么握手需要三次,而挥手却需要四次?
握手的时候,A和B打个招呼,B可以直接把自己的SYN信息和对A的回应ACK信息一起带上,但是挥手的时候,A说我要断开了,B还没发完最后的数据,因此需要先回应一下A,我收到你的断开的请求了,但是你要等我把最后的内容给你,所以这里分开了2步: (1)回应A; (2)发送自己的最后一个数据
2.为什么A进入TIME_WAIT需要等待最大报文段生存的时间后,才能关闭?
原因是,担心网络不可靠而导致的丢包,最后一个回应B的ACK万一丢了怎么办,在这个时间内,A是可以重新发包的,但是超过了最大等待时间的话,就算收不到也没用了,所以就可以关闭了。
如何理解滑动窗口的作用?
从上面的内容,我们简单了解了三次握手和四次挥手的内容,然后也知道了一些报文字段的意义,但是网络本身是不稳定的,也就是说中间无法保证数据包一定会到对面,那么tcp是如何在尽可能少的时间内实现稳定和有序传输的?
我们知道SYN信息中会带上自己的seq,序号,这样可以保证另一方接受到后知道如何排序,但是如果发送必须都是同步的,想象,A 给 B发送的时候,需要给B 1,2,3,4,5个包,发了1后,死等1的ack回来,再给2,死等2的ack回来,在 linux 下每个tcp的timeout最大是 2^5 - 1 = 63
s(默认的retrytime是5次)的时间,因为当发了一个包出去后,在一定时间内没收到ACK回应,为了确认不能丢包的问题,会启动重试机制,重试5次,它们的延迟分别是:1 秒、3 秒、7 秒、15 秒、31 秒,其中31s是前5次重试的时间1+2+4+8+16=31s,最后的32s是等待最后一次重试也超时(等待的时间是2的N次方秒),所以一共就是63s,如果一个一个等,是不是有点太恐怖了,万一网络环境比较差,所以为了能在不丢包的情况下,尽量减少时间的损耗,引入了滑动窗口的概念,window
由于窗口由16位bit所定义,所以接收端TCP,窗口能最大提供65535个字节的缓冲,其实这个滑动窗口主要就是做限流和缓冲用的,每一个tcp传输中的win提供的是对方的窗口大小,当A向B发数据的时候,超过B的win长度的数据会被丢掉,同时窗口还可以提高发送数据的效率,通过类似于并发的行为,如下图:
可以看到A向B连续发了3条数据,但是回应B的ACK没有变,也就是说都是回应同一个B的同一个响应,但是A自己的seq更新了3次,先是1,然后是69最后是1521,说明这三个包是连续发出去的,实际上只要当前数据包的大小不超过对方的window大小,就可以连续发的,接着看:
这四个是B响应给A的数据包,可以看到都是在响应A给的数据包,注意看因为A连续发了好几条,B可能一下反应不过来,所以B会把这些信息放到缓冲区,但是放的数据越多,那么自己的缓冲区就越小,就是通过B自己的win来体现,我们可以看到B的win再连续变小,说明它还没处理好,到第4条信息的时候,我们看到B给了一个信息叫WINDOW UPDATE 然后发现B的win变大了,这就意味着它已经处理好A之前连续发的几个数据包了,然后就会重新更新自己的win的大小,要注意的是当tcp一端的win接近或者等于0的时候,传输将会停止,直到window update更新说buffer已经清空了,传输才会继续。
丢包?
看下面这个图
明显能看到ACK是连续变大的,在一次连接中,不可能存在说先回复ACK=3922然后再回复ACK=3913,这样的话另一端在收到3922的时候就认为之前的全部接收到了,实际上3913还没收到,要注意SeqNum和Ack是以字节数为单位,所以ack的时候,不能跳着确认,只能确认最大的连续收到的包。那么,考虑以下情况,假如A给的分别是1,2,3,4到5 5个包,B这边收到1,Ack一个2(代表收到1了),然后2丢了,3、4和5收到了,能直接ACK = 6吗?当然不行,这样的话tcp就是不稳定的了,考虑超时重传的2种方案:
1.timeout后只重新传2; 2.timeout后重新给2、3、4、5;
2种方案有好有坏,第一种比较慢,第二种浪费带宽,所以tcp引入了一种快速超时重试机制(Fast Retransmit算法),不以时间计算,而以数据做驱动重新传送,如果包没有连续到达,比如1到了,2没到,3,4,5也到了,这个时候,B始终返回ACK=2,代表只确认1,然后A就知道2没到,重新发2,但是B一旦收到2会直接ACK=6给A,这个的意思就是说2拿到后,345也收到了,直接给6就ok,如下图:
上面说的只是一种特别简单的方案,目前,linux2.4之后,采用了一种更先进的方式,有想了解的可以走这里
攻击
典型的场景是DDOS攻击,也可以说是tcp的SYN Flood攻击,又叫洪水攻击; 根据上面的分析,我们知道tcp的握手环节是比较耗时的,当client端发起连接请求的时候,server端会回应,然后等待client的最终确认信息,默认情况下的linux会等待1到63s这样(如果有特殊的设置,这个时间可以到1-2min这样),默认最长是63s之后才会断开,之前这段时间内属于半连接的状态,服务器不会丢弃掉这些连接,而是会等,试想如果有一个人突然想你的server瞬间之内发送了几千万个连接请求,但是对服务端的响应不做理睬,这样很容易就导致我们正常的tcp连接进不去,从而出现服务拒绝的情况,而他只需要一个简简单单的脚本去给你丢包就可以了,这种情况就会导致服务器对正常的客户端表现为宕机。。此种攻击的成本比较低,但是防护却特别麻烦,因为你必须要保证正常的不能因为访问次数的提高而出现拒绝。
另外一个没有这个情况严重的攻击是ACK Flood攻击,有兴趣的可以自行去查看。
TCP是个巨复杂的协议,我们今天通过一次抓包了解了三次握手,四次挥手,滑动窗口。超时重传机制和典型的tcp攻击方式,希望能对各位看官对tcp的认识有一定的帮助;
以上所述就是小编给大家介绍的《作为前端的你了解多少tcp的内容》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 作为一个前端,可以如何机智地弄坏一台电脑?
- 作为一个前端工程师也要掌握的几种文件路径知识
- 使用Elasticsearch作为主数据存储
- 如何把MongoDB作为循环队列
- 使用 utterances 作为博客评论组件
- 作为项目经理应该串联起哪些流程
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
并行计算导论
Ananth Grama、George Karypis、张武、毛国勇、Anshul Gupta、Vipin Kumar、程海英 / 张武、毛国勇、程海英 / 机械工业出版社 / 2005-1-1 / 49.00元
《并行计算导论》(原书第2版)全面介绍并行计算的各个方面,包括体系结构、编程范例、算法与应用和标准等,涉及并行计算的新技术,也覆盖了较传统的算法,如排序、搜索、图和动态编程等。《并行计算导论》(原书第2版)尽可能采用与底层平台无关的体系结构并且针对抽象模型来设计处落地。书中选择MPI、POSIX线程和OpenMP作为编程模型,并在不同例子中反映了并行计算的不断变化的应用组合。一起来看看 《并行计算导论》 这本书的介绍吧!