经常有人问:当你在浏览器敲下回车键发生了什么?
https://img-blog.csdnimg.cn/20200526213649580.jpg?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgxMDgwMg==,size_16,color_FFFFFF,t_70" alt="" />
比如请求百度的网站。
dns解析这一块我们就不讲了。
拿到百度的ip地址后,浏览器要干什么呢?
它会像java一样new一个Socket。这是用户空间的操作,new好一个Socket之后发生了什么呢?
接下来的工作就是内核空间的事情了,程序员是接触不到的。
并不是说,我浏览器new了一个Socket,你百度服务器就会和我建立连接,然后进行数据传输。因为我们首先要确保连接上了,然后才能开辟资源为传输数据做好准备。
那么谁去干这个确保连接的事情呢?
这活交给传输控制层干。和网络层所用的http协议不一样,传输控制层用的是tcp协议。
tcp协议就是所谓的面向连接的可靠的传输协议。
什么叫面向连接的可靠的传输协议呢?
先说不可靠的udp传输。比如你上网课,对面老师的一个讲课画面可能卡住了,然后你就等卡住的画面过去。
udp不管你收没收到数据包,它就一直传过来。中间如果丢包了,那么就会导致画面卡住。
tcp不同,它的可靠性来源于三次握手:
A:我准备好了。
B:我听到了,我也准备好了。
A:我听到了。
为什么要三次?这里解释的很清楚。当B回我也准备好了的时候,B不知道A到底有没有收到,它心里没有底。所以A最后还要回个话让B知道自己发出去的信息A收到了。
讲到三次握手,就要讲四次分手。
为什么要分手?因为端口号有限,因为要释放资源。
A:我们分手吧。
B:好的。
B:我们分手吧。
A:好的。
这就是所谓的四次分手。tcp是一个协议,不是你单方面断开连接就行了,这是不合规矩的。
上面的四次分手,是一种双方同意的结果。
我们用一个tcpdump命令看一个实战:
tcpdump -nn -i en0 port 80
这个命令是用来抓包的,是wireshark的简化版。
-nn表示我们要展示ip地址和port,不要给我翻译成域名。
-i是interface,就是网卡接口。我们监听en0上的数据传入传出。
然后监听80端口。
一敲回车,阻塞了。
另外开一个窗口:
curl www.baidu.com
请求百度。
回来看tcpdump捕获的结果:
https://img-blog.csdnimg.cn/20200526215707195.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgxMDgwMg==,size_16,color_FFFFFF,t_70" alt="" />
https://img-blog.csdnimg.cn/20200526215907634.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MzgxMDgwMg==,size_16,color_FFFFFF,t_70" alt="" />
[S]表示发一个sync包。
[.]表示ack,就是acknowledge,确认的意思。
[F]表示final,就是结束了。
[R]表示connection refused,就是连接被拒,就是断了连接了。
有时候因为网络延迟,数据可能会重发。所以会有sack,即selective acknowledge。意图是告诉对面,你这个包发过了,不是我没收到,是网络延迟了。
tcp数据包有了,里面装了百度的ip地址。现在我要查路由表了,下一步该怎么走?
(我换了个电脑,所以就网卡就不一样了)
https://img-blog.csdnimg.cn/20200526220913233.png" alt="" />
路由表第一条就匹配了。
将百度的ip地址与掩码做与运算,符合destination,于是找192.168.8.1
这个地址。
192.168.8.1
当然就是我的路由器的ip地址。
现在的问题是,它在哪里?换句话说,它的mac地址是什么?mac地址就像一个人的身份证一样,我要给你传数据,必须要知道你的mac地址。
继续往下一层走。于是我们到了链路层。链路层有arp协议,里面也有一张表:
https://img-blog.csdnimg.cn/20200526221812286.png" alt="" />
它告诉你192.168.8.1
这个ip地址对应的mac地址。这下,我的tcp数据包就可以发给路由器了。至于接下来路由器怎么办,我就不管了。