《网络是怎么样连接的》读书笔记 - 汇总篇(一)

本文涉及的产品
.cn 域名,1个 12个月
全局流量管理 GTM,标准版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 《网络是怎么样连接的》读书笔记 - 汇总篇

引言

其实就是把之前的内容汇总到一个文章方便阅读。为了节省大家的时间,建议挑自己感兴趣的内容看,而不是从上往下看,建议看一切文字材料都保持这样的习惯。

image.png

资源链接

《网络是怎么样连接的》电子书资源,包含PDF和EPUB。

链接:pan.baidu.com/s/15IGzN4xt…

提取码:f5sy

历史文章汇总

必看章节:

[[《网络是怎么样连接的》读书笔记 - 认识网络基础概念(一)]] [[《网络是怎么样连接的》读书笔记 - Tcp-IP连接(二)]] [[《网络是怎么样连接的》读书笔记 - 集线器、路由器和路由器(三)]]

选看章节:

[[《网络是怎么样连接的》读书笔记 - 服务器端的局域网中(四)]] [[《网络是怎么样连接的》读书笔记 - WEB服务端请求和响应(五)]]

非必看章节:

[[《网络是怎么样连接的》读书笔记 - FTTH]] [[《网络是怎么样连接的》读书笔记 - ADSL]]

《网络是怎么样连接的》读书笔记 - 认识网络基础概念(一)

本章重点

  1. 关于互联网的一些历史补充
  2. 解析URL的过程简述
  3. HTPP请求的基本结构和组成
  4. IP 地址、子网掩码以及DNS的基本了解,掌握概念和相关知识点。

讲讲历史

1991年8月6日,在瑞士日内瓦的核子研究中心(CERN)工作的英国物理学家蒂姆·伯纳斯·李(Tim Berners-Lee),正式提出了World Wide Web,也就是如今我们非常熟悉的www。

www是什么?万维网WWW是World Wide Web的简称,也称为Web、3W等。WWW是基于客户机/服务器方式的信息发现技术和超文本综合技术

这里个人比较好奇我们天天都在说3w,3w,但是互联网是怎么出现的的书中并没有解释?

这里查了下网上资料根据个人理解解释一波:

实际上网络最开始苗头出现在美苏冷战的时期美国建立的APRA科研部门,被突然扯出来的科研部门一盘散沙不知道干嘛,对付苏联的科研工作也没什么进展,直到一个叫做罗伯特·泰勒的哥们出现,他的突破口是发现小型的通信网络不能兼容不同型号的计算机,我们都知道技术的顶峰就是定规则,毫无疑问他选择构建一套协议让所有的计算机都能遵守这一套规则干活。

于是他找来了几个牛逼的大佬开始捣鼓,中间巴拉巴拉做了很多事绕了很多弯,目的其实就是为了实现上面说的东西,最终在一次失败的“LOGIN”验证中虽然仅仅传输了“LO”两个字母就断开了,但是这次失败是历史性的进步,因为两个不同的设备实实在在的通信了,最终修复之后完成了这五个字母的正常传输。

随后捯饬出的ARPANET(阿帕网) 这个项目,也就是正式的互联网雏形。

课外知识到此结束,现在我们看看第一章主要看点:

  1. 如何解析网址?
  2. DNS 服务器如何查询域名对应的 IP 地址?
  3. DNS服务器如何接力?
  4. 浏览器如何将消息委托给操作系统发送给 Web 服务器?

核心是理解DNS的角色地位和作用,以及浏览器如何跟DNS交互完成网址(域名)解析为IP这一个操作的,本章最后的委托流程是整个第二章的重点内容,笔记顺其自然的放到了第二章笔记当中,为了方便理解把笔记归纳到第二部分。

如何解析网址

我们从URL开始,什么是URL,URL是Uniform Resource Locator的简称,专业解释叫做统一资源定位符,除开我们常见的http、https协议之外,浏览器还可以进行ftp文件上传,下载文件,发送电子邮件,浏览新文化等操作。

我们把这些行为看作是资源交互,虽然不同的资源交互会存在不同的URL组合,但是不管URL的组合形式如何变化,最终是开头决定一切,开头部分决定对待资源方式。

解析网址我们可以看下面的例子:

image.png

碰到省略文件名的情况,通常下面几种:

  • http://xxxx/dir/表示 /dir/ 之后的内容被省略,这时候通常情况下会设置对应这个目录的真实访问路径进行补全
  • 对于web中最为经典的http://localhost:8080/访问路径,通常情况下Web服务器会访问到/index.html这个文件,如果没有就会返回404的页面。
  • 如果只有域名,比如www.baidu.com,那就会直接访问web服务器设置的根路径对应的资源和相关文件。
  • 含混不清的路径比如http://localhost:8080/wishlist,则会根据先判断是否为文件名,然后判断是否为目录的情况处理,或者看作一个请求映射到另一处资源,或者做一次重定向。

上面的内容不必深究,只需要明白浏览器的第一步工作就是对 URL 进行解析

Http请求

http请求简单来说可以简单概括为一句话:对什么做了什么样的操作,所谓对什么指的是URL,表示标识了的目标对象,做什么样的操作就是所谓的方法,方法主要是分为两个POSTGET方法,其他方法基本没啥用处,个人只在偶尔几个对接文档中遇到过PUTHEAD方法。

image.png

GET方法:通常用于一些可见资源的访问,或者开放资源的访问,通常情况下不需要过多的限制就可以直接向具体的目录寻找需要的资源。

POST方法:比较常见的是使用表单或者 AJAX的方式访问,并且通常会指向一个WEB的应用程序,获取应用程序的数据需要传递服务器需要的一些有效参数,否则服务端会根据具体情况通知客户端无权访问。

AJAX即“Asynchronous JavaScript and XML”(非同步的JavaScriptXML技术),指的是一套综合了多项技术的浏览器网页开发技术。Ajax的概念由杰西·詹姆士·贾瑞特所提出[1]

Http请求消息

知道了 对什么做了什么样的操作,现在来看看Http 具体是怎么做这件事情的。

Http请求消息主要分为下面组织结构:

  • 第一行最开头的部分提取URL的内容,原封不动解析,末尾为HTTP版本号主要标记当前HTTP请求版本。

例如:GET /cgi/sample.cgi?Field1=ABCDEFG&SendButton=SEND HTTP/1.1

  • 第二行为消息头,这里列举一些简单的内容:
  • Data:请求响应生成日期。
  • Pragma:数据是否允许缓存。
  • Transfer-Encoding:消息主体编码格式(重要)。
  • Via:经过的代理和网关。
  • 消息头后面存在一行 完美没有内容的空行
  • 第四行为消息体,但是实验用的是GET方法所以通常内容为空。

image.png

我们以访问谷歌为例,下面的内容访问谷歌搜索页面的一次请求参考,这里的内容直接通过谷歌浏览器的F12拷贝,可以看到基本包含了请求行,消息头和消息行(GET通常没有所以下面没有体现)三种。


常规
1.  请求网址:https://www.google.com/
2.  请求方法:GET
3.  状态代码:200
4.  远程地址:127.0.0.1:7890
5.  引荐来源网址政策:origin
请求标头
1.  :authority:www.google.com
2.  :method:GET
3.  :path:/
4.  :scheme:https
5.  accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
6.  accept-encoding:gzip, deflate, br
7.  accept-language:zh,zh-TW;q=0.9,en-US;q=0.8,en;q=0.7,zh-CN;q=0.6
8.  cache-control:no-cache
9.  cookie:SID=KQi0QVpC_wxTynb6H6HjGmVq-9mYvCuIDOMx9EmEUJ8ii7dJzN_1F-ho69FdK6AN9ekOkA.; __Secure-1PSID=KQi0QVpC_wxTynb6H6HjGmVq-9mYvCuIDOMx9EmEUJ8ii7dJaTdIpqSfRfNb-BvF0haitA.; __Secure-3PSID=KQi0QVpC_wxTynb6H6HjGmVq-9mYvCuIDOMx9EmEUJ8ii7dJ6_WQQeEF09oAZ9MQfe21sA.; HSID=AOdmIhuBCutDeMwVS; APISID=ckyVXTB27QMaC2gQ/AVulr1cMnMbpD0e1x; SSID=AL0-0R0Ofsj3zaqrr; SAPISID=dqpTwJeh7bnii2Ki/AfsaDUfE8uMVR1aqv; __Secure-1PAPISID=dqpTwJeh7bnii2Ki/AfsaDUfE8uMVR1aqv; __Secure-3PAPISID=dqpTwJeh7bnii2Ki/AfsaDUfE8uMVR1aqv; SEARCH_SAMESITE=CgQIvJUB; 1P_JAR=2022-05-24-23; AEC=AakniGOKhznRpAD797X4u508i2XHJjEVYQQHANlqaJC2JSZ1F7mAe-vX_rg; NID=511=K-qt_LW-4ad1IYdJgfPLZjJw772wez2L3_FK9hwrrHAaksdhT8bTqz4icJEnJviOb92zcnyfS4h7P8HB_Is0f_FebYTe_5DR3qFEclHS1R9N1P7r9pv7Z4p12341S72RZRfzIlQ3-CVZUqQKBm1Xy1i9fKwejMGHTPMY2hk02sA--ey8nAEyt1_A7SVMe0RvrEkPnVm88fBnyyyFMMSCeSG1oqYKeC2x7iHJ0GwdbEpeGojpMQyQxAn1jAdxyXbC0oko0rCFjYn7eUREz2A9KA; SIDCC=AJi4QfGQeW0y_3pnzuBs7KI-WabF5XR_-dQchpcoNUN_bRVICBknb39qNQhP4IklnPn6kW4M3d8; __Secure-3PSIDCC=AJi4QfFOaoqiWv0mqmOskkIKVYy_-QNOATkPOyhNt9B8BBTMnRqnv-0zdgVgBNmIJRwlzBS4x6U
10.  pragma:no-cache
11.  sec-ch-dpr:2
12.  sec-ch-ua:" Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"
13.  sec-ch-ua-arch:"arm"
14.  sec-ch-ua-bitness:"64"
15.  sec-ch-ua-full-version:"101.0.4951.64"
16.  sec-ch-ua-full-version-list:" Not A;Brand";v="99.0.0.0", "Chromium";v="101.0.4951.64", "Google Chrome";v="101.0.4951.64"
17.  sec-ch-ua-mobile:?0
18.  sec-ch-ua-model:""
19.  sec-ch-ua-platform:"macOS"
20.  sec-ch-ua-platform-version:"12.3.1"
21.  sec-ch-ua-wow64:?0
22.  sec-ch-viewport-width:1440
23.  sec-fetch-dest:document
24.  sec-fetch-mode:navigate
25.  sec-fetch-site:same-origin
26.  sec-fetch-user:?1
27.  upgrade-insecure-requests:1
28.  user-agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.64 Safari/537.36
29.  x-client-data:CLG1yQEIkrbJAQijtskBCMS2yQEIqZ3KAQjYjMsBCJShywEI2+/LAQjmhMwBCNupzAEI/qrMAQjDrMwBCKSvzAEYqKnKARirqcoB
30. 已解码:message ClientVariations { // Active client experiment variation IDs. repeated int32 variation_id = [3300017, 3300114, 3300131, 3300164, 3313321, 3327576, 3330196, 3340251, 3342950, 3347675, 3347838, 3348035, 3348388]; // Active client experiment variation IDs that trigger server-side behavior. repeated int32 trigger_variation_id = [3314856, 3314859]; }

响应内容

响应页面也是类似的需要回应请求行需要的内容信息,同时告知自己允许接受什么样的请求,如果目标IP找不到通常会变为404结果。


响应标头
1.  accept-ch: Sec-CH-Viewport-Width  
2.  accept-ch: Sec-CH-Viewport-Height
3.  accept-ch: Sec-CH-DPR
4.  accept-ch: Sec-CH-UA-Platform
5.  accept-ch: Sec-CH-UA-Platform-Version
6.  accept-ch: Sec-CH-UA-Full-Version
7.  accept-ch: Sec-CH-UA-Arch
8.  accept-ch: Sec-CH-UA-Model
9.  accept-ch: Sec-CH-UA-Bitness
10.  accept-ch: Sec-CH-UA-Full-Version-List
11.  accept-ch: Sec-CH-UA-WoW64
12.  alt-svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000,h3-Q050=":443"; ma=2592000,h3-Q046=":443"; ma=2592000,h3-Q043=":443"; ma=2592000,quic=":443"; ma=2592000; v="46,43"
13.  bfcache-opt-in: unload
14.  cache-control: private, max-age=0
15.  content-encoding: br
16.  content-length: 43734
17.  content-type: text/html; charset=UTF-8
18.  date: Tue, 24 May 2022 23:24:59 GMT
19.  expires: -1
20.  server: gws
21.  set-cookie: 1P_JAR=2022-05-24-23; expires=Thu, 23-Jun-2022 23:24:59 GMT; path=/; domain=.google.com; Secure; SameSite=none
22.  set-cookie: AEC=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=www.google.com
23.  set-cookie: AEC=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.www.google.com
24.  set-cookie: AEC=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=google.com
25.  set-cookie: AEC=; expires=Mon, 01-Jan-1990 00:00:00 GMT; path=/; domain=.google.com
26.  set-cookie: SIDCC=AJi4QfEXTiPm1BcAx1gfQzXOs-hmdcHylOVoSbbpy8cUIlP7hNwwfnfo_E8ZdTY1JZli8AqYYWk; expires=Wed, 24-May-2023 23:24:59 GMT; path=/; domain=.google.com; priority=high
27.  set-cookie: __Secure-3PSIDCC=AJi4QfFdxOIbJrwDKltt2sBRVFIcLOCyqQmgTSfYjXTYwqbhh0GPLcR9cxsgyaIh1j_GITbGeHc; expires=Wed, 24-May-2023 23:24:59 GMT; path=/; domain=.google.com; Secure; HttpOnly; priority=high; SameSite=none
28.  strict-transport-security: max-age=31536000
29.  x-frame-options: SAMEORIGIN
30.  x-xss-protection: 0

响应内容相对比较简单,主要关注重点为第一行内容中的状态码和响应短语,请求执行结果是成功还是失败。上面的交互内容需要注意Http请求严格遵循一个请求对应一个响应内容。

注意:1 条请求消息中只能写 1 个 URI。如果需要获取多个文件,必须对每个文件单独发送 1 条请求。

“如何解析网址?”这个问题从头到尾的介绍到这里就完成的,接下来来看看下一个问题"DNS 服务器如何查询域名对应的 IP 地址?"。

IP 和 DNS

首先我们看看IP和DNS是啥,解析网址(域名)和发送请求和响应内容看似是浏览器完成的,实际上它并不具备这些功能, 浏览器收发网络请求实际上需要依托操作系统完成 ,而现代网络基本是TCP/IP 的天下,所以IP发挥关键作用,而DNS存储IP和域名映射的仓库。

  • IP:可以类比做我们现实的具体位置,比如XX路XX号,XX路(网络号)对应的的是分配给整个子网的号码,而XX号(IP地址)的号码则分配给子网中的计算机,获得到IP地址之后就相当于锁定了当前计算机所在的具体位置,自然也可以可以找到了。
  • DNS:直白来讲就是存储了域名和IP映射的记录的站点,浏览器要获取真实地址需要找DNS才能知道,因为域名放任用户自由定义将会出现同一个域名映射多个IP。

下面我们先观察XX路XX号的号也就是IP地址是如何被找到的。

发送网络的一方通过子网首先需要经过集线器,把内容转发到最近的路由器上,然后路由器会不断跨越找到离接受者更近的下一个路由器,最后再找到集线器然后在转发到接收者的路由器上,路由器在这里是方向盘的角色,而DNS寻址就像是导航。

image.png

集线器和路由器是什么? A 路由器:一种对包进行转发的设备。 B 集线器:一种对包进行转发的设备, 分为中继式集线器和交换式集线器两种.

IP地址的组成

IP地址是一个32位的Bit数,通过8个bit为一组分为4组,每一组用十进制表示并且使用小圆点断开。

但是仅凭这32个bit是无法定位IP地址和网络号的,所以需要给IP地址附加信息。

通常IP地址的组合有下面的方法:

a)IP地址主体:11.22.33.44

b)IP和子网掩码:11.22.33.44/255.255.255.0

c)网络号的比特数作为子网掩码表示:11.22.33.44/24

d)子网地址:11.22.33.0/24,此时代表了整个子网

e)子网广播地址:11.22.33.255/24

首先整个IP分为32位固定长度,每四个为一组用圆点分隔,通过 0 - 255的十进制表示,比如0就是8个0,255就是8个1,但是仅仅凭借32个位数是没法辨别这32位那一部分是网络号,那一部分是主机号的,所以下面是IP的基本组成:

  • 11.22.33.44:表示基本的IP。
  • 11.22.33.44/255.255.255.0:前面部分是基本IP,后面的部分表示子网掩码,表示方式和IP地址一致,注意最后的8位全部为0表示整个子网。
  • 11.22.33.44/24: 这个24也是子网掩码,但是表示子网的方式是使用比特数。
  • 11.22.33.0/24: 子网掩码没有变,IP地址变了,最后的8位0也是表示整个子网。
  • 11.22.33.255/24: 子网掩码没有变,IP地址变了,最后的8位全部为1表示广播 整个子网。

什么是子网掩码?

初学者可能比较难以理解的概念,这里如果看不懂建议多找找资料挑一个看得懂的解释(关键是自己理解并且能自己复述)。

下面是从书中原图,个人看完感觉并不是特别直观也不知道干嘛,所以做了一个补充说明。

实际上下面图中网络号用了AND(位操作 &)计算出网络号码,计算之后确认出网络号是10.1.2,而后面省略的部分其实是8个0的掩码掩盖主机,这里的子网就是 10.1.2.0,对应的主机IP是10.1.2.3。

image.png

如果看不懂上面说的是啥,这里补充解释一下:

首先我们需要清楚子网掩码这东西是干嘛的,说白了就是划分网络号和主机号的,网络号可以看作一栋楼,主机是里面的小房间,但是房间编号可能是101,也可能是0101,更有可能是00101,具体得看掩盖的房间号从0000到1111有多少个,决定能分配给多少主机,而计算机0又很特殊,所以网络号的部分+ 子网掩码掩盖的位数部分(表现全为0)组成一个子网,只有在同一个子网的主机才能互相通信

所以子网掩码不能单独存在,它必须结合IP地址一起使用,子网掩码主要分为两个部分:全为1表示网络号,全为0表示的是主机号。

那么我们随便设置一个子网掩码比如255.255.255.111行不行?

答案是不行不行不行。因为子网掩码 必须是 连续的 1和0 组成,上面的掩码255.255.255.0 才是正确的用法,再举例比如255.255.255.244也是合格的子网掩码。

我们举例说明一下:


1100 0000.1010 1000.0000 0001.1000 0001 -- 192.168.1.129
1111 1111.1111 1111.1111 1111.0000 0000 -- 255.255.255.0
———————————————————— 
1100 0000.1010 1000.0000 0001.0000 0000 -- 划分出最终子网网段:192.168.1.0
注:确认最终的网络号和主机网段使用了位操作 & (1 & 1 = 1,1 & 0 = 0)

从最终的结果来看192.168.1.0 的前面24位都为1是暴露的,而后面8位被子网掩码给遮掩住,所以他的另一种写法是192.168.1.0/24,表示24位是1代表网络号,剩余的8位用于表示主机号但是因为被掩盖了所以全部为0。

虽然被掩盖了,但是主机号位置是0是1不需要关心的,主机号如果落在192.168.1.0192.168.1.255表示同在一个网段内子网一视同仁,比如192.168.1.129表示其中的129位,包含在这个网段之内。

小结

  1. 子网掩码 必须是 连续的 1和0 组成,简单记忆为1的部分来分割网络号,为0的部分用于掩盖主机号,同一个子网内的主机可以互相通信。
  2. 子网掩码有两种写入方式一种是使用和I P 地址一样的32位完全表示方式,另一种是使用数字计算1比特数进行替换,比如24就是下面图中的24个1。
  3. IP 地址的主机号,全 0表示整个子网,全 1表示向子网上所有设备发送包。这里补充一下全为1的情况 - “广播”。

广播是什么意思?广播地址是专门用于同时向该网络中所有主机进行广播的一个地址,只要是在同一个网段的主机都可以收听到广播。(例如192.168.211.32/24的广播地址为:192.168.211.255

DNS

DNS: Domain Name System域名服务系统,最常见的用法是将服务器名称和 IP 地址进行关联,当然只是它的主业,有一些副业也挺重要但是不是关键感兴趣了解即可。

IP是难以记忆的,而简短域名更容易被人记住。你可能会觉得域名长了也难记忆啊,虽然解析IP的速度要比解析域名来的快的很多,但是显然网民为了访问一个网站要记住一串数字显然是不可能的,同时域名实际上对于当时的互联网发展来说也是有意义的。

所以谁来告诉主机域名的真实IP是多少?这时候DNS就上场了,DNS的作用是说白了就是用来映射IP和域名的一个东西。

DNS是如何完成映射的?对于用户主机来说一定存在一个用于解析DNS的客户端,这个客户端通常被称为解析器,通过域名解析出IP地址的过程也被称为域名解析

调用解析器

那么如何调用解析器?解析器实际上就是一段程序代码,这一段程序代码包含在底层操作系统的Socket库当中,通过Socket库调用解析器,然后解析器会向 DNS 服务器发送查询消息, DNS 服 务器根据请求查询IP然后返回响应消息。

Socket 解析域名的过程非常简单,只需要一行代码就可以完成:gethostbyname("www.lab.glasscom.com");

库:指的是通用程序组件的集合,用于规范程序代码的规范组建。以解析器为例,Socket 库是用于调用网络功能的程序组件集合。

解析器内部又是如何工作的?

在应用程序调用解析器的时候,此时控制权会转移到解析器,当控制权转为解析器之后解析器会生成要发送给 DNS 服务器的查询消息,生成过程类似构建一条“请告诉XXX的IP地址”的消息,并且发给DNS服务器完成解析。

特别注意注意发送请求不是由解析器完成,而是需要再次委托给操作系统的协议栈完成,所以此时权限会再次转移到协议栈,协议栈最终通过网卡把消息发给DNS,然后DNS查到IP返回消息,至此一次DNS解析请求就完成了。

值得注意的是 解析器会将取出的 IP 地址写入应用程序指定的内存地址中,此外还需要注意请求DNS服务器本身IP也是需要配置的,只不过这个 IP 地址是作为 TCP/IP 的项目事先设置好的,不需要再去查询直接就可以获取。

最后在不同的操作系统中获取DNS服务器的地址方式会有差别。

根据上面的描述,总结DNS解析流程:

  1. WEB浏览器发送域名解析请求,通过Socket向解析器进行请求解析,此时应用程序将会挂起。
  2. 解析器负责“翻译”应用程序的DNS解析请求,但是把具体的请求操作委托给系统栈。
  3. 系统栈负责将请求通过网卡发送给DNS服务器,等待DNS反馈结果。
  4. DNS获取真实IP之后将结果通过链路反向回送到应用程序。

image.png

DNS工作

接下来我们看看dns要如何工作,dns需要查询用户消息包含下面几个部分:

  • 域名:用来替代IP方便记忆。
  • class:考虑到互联网之外的情况,当然外部网络现在只有标识为in的互联网。
  • type:表示记录类型用于区分dns的解析方式,不同类型结果不同。

需要注意的是所有a类型的记录在DNS上注册了,再比如所有邮件类型都是MX的类型,整个DNS工作其实就简单的根据类型和域名进行查表,找到匹配的就回传,否则就会找不到。

域名层次:所谓域名层次就是DNS不可能是一台服务器,而是需要多台服务器配合,各自管理自己范围的内容,而对于域名来说越靠右边的部分在域名的层次里面越高。

这样看来是不是有点意思,以日常生活举例并不是我们认为的www是最高,其实他是最低的等级,.com才是最高的。

DNS查找步骤

首先将负责管理下级域的 DNS 服务器的 IP 地址注册到它们的上级 DNS 服务器中,然后上级 DNS 服务器的 IP 地址再注册到更上一级的 DNS 服务器中,以此类推。

举个例子,需要解析等域名为www.baidu.com,DNS需要事先把整个www.baidu.com整个域名注册到baidu.com,再把baidu.com注册到com域名,再把com注册到根域,这样就可以通过上级找下级。

这里提到DNS有一个根域,根域名指的是就是一个句点 . ,和Linux的根路径意义表现形式上类似。

根据根域可以解释为什么任何奇怪等域名都可以被访问到,原因是所有的下级都会注册到上级中,最后都有一个共同的 ,如果所有下级要找到根域,自然需要注册根域这个句点。

DNS查找的过程是自下而上找最近的DNS然后自上而下找根域向下查找的的,也就是先找最近的dns找,没有找到就需要直接从根域进行查找,一路通过层级下探找到最终的ip,这也是为什么访问国外ip慢的原因,因为路由链路实在是很长,可能需要几十次dns搜索查找。

image.png

DNS缓存

如果每个主机每次请求总是要通过DNS获取域名对应的IP信息,是不可能每次都DNS让找一遍的,实际上解析到的真实IP会预先缓存起来下次访问重复的数据直接返回即可。

另外虽然前面介绍的是查找自上而下从根域向下查找,实际上DNS还可以利用缓存特性通过多个层级的共享域名加快访问速度跨级查找,比如www.baidu.comwww.baidu 可以共享缓存直接跳两个层级快速找到(当然这里其实找最近的一个DNS就能找到,这里仅仅是举例)。

但是缓存有个副作用,就是不存在的ip地址消息也会缓存,不过为了防止这种情况一般会有过期时间,过期之后依然需要再次走一遍DNS查找流程。

问题引导:问题

表示的是HTTP 协议

  • 下面两个网址有什么不同?

a. www.nikkeibp.co.jp/sample

b. www.nikkeibp.co.jp/sample/

区别点在于sample 可能被解析出和预期不符合的结果。

用来识别连接在互联网上的计算机和服务器的地址叫什么?

IP地址

根据 Web 服务器的域名来查询 IP 地址时所使用的服务器叫什么?

DNHS服务器

向 DNS 服务器发送请求消息的程序叫什么?

解析器。

《网络是怎么样连接的》读书笔记 - Tcp/IP连接(二)

TCP和IP协议承载了整个互联网的生命线,这一章算是本书核心部分,掌握这两个协议也是学好网络编程的基础。

本章重点

  1. Socket客户端连接细节,可以结合第六章服务端接收的细节对比学习
  2. IP和以太网的报文内容,以及MAC网络包如何封装,这里可以参考5层模型了解熟悉整个步骤
  3. UDP收发数据细节。

Socket连接

套接字链接在表面上看就是建立连接,交换数据,断开连接,虽然实际上细节肯定没有那么简单,但是大体上的思路基本不变。

协议栈建立连接

这里记住一个前提:向操作系统内部的协议栈发出委托时,需要按照指定的顺序来调用 Socket 库中的程序组件。

建立Socket的协议大部分情况都是Tcp/ip协议,Socket收发数据类似在两个主机之间建立一个无形的管道,Socket建立的关键是要按照指定顺序调用Socket程序组件,大致的构建顺序如下:

  1. 创建Socket(Socket类似管道两边的出入口)
  2. 绑定客户端的套接字到服务端(类似接管道)
  3. 交换数据。
  4. 断开Socket连接,解除绑定。

转化为具体的流程图如下:

image.png

创建Socket

过程大致为应用程序会把控制流程会转移到 socket 内部并执行创建套接字的操作,完成之后控制流程又会被移交回应用程序。

创建完套接字之后,协议栈需要返回标识符号也就是描述符用于标识是哪一个套接字在进行传数据,因为我们可能打开很多套接字连接访问不同的网站,具体的效果是我们浏览器会打开很多个页面,这时候每一个页面都可能需要创建套接字,此时就需要识别和区分这些套接字依赖描述符。

绑定客户端的套接字到服务端

连接操作核心是调用Socket的connect连接方法,此方法需要指定描述符、 服务器 IP 地址和端口号这 3 个参数。

connect看上去挺复杂,其实本质上就是完成连接动作而已,连接成功会把IP地址和端口号记录到套接字上面。

描述符在创建Socket的时候已经拿到了,IP地址则是在DNS解析的步骤完成,拿到IP之后会放入到应用程序的某个位置替换保存,而端口号则是需要应用程序事先提供。

端口可以简单看作应用程序的入口,DNS解析的IP只能知道主机在哪但是本身发往哪个应用程序是不清楚的,我们可以想象DNS解析类似地图上告诉我们高速的收费站坐标,但是他并不知道对应数据送往那个闸口)。

这里可以理解为端口就是收费站过站口,计算机会要求程序对待应用程序预设明确的端口参与网络交互。

传递消息

接下来的操作是调用read和write函数完成消息传递动作,这一步就是底层的流读写操作。

断开连接

这一步需要简单理解为需要一方主动发起断开申请浏览器调用read收发数据同时会收到关闭请求,此时客户端确认请求之后将会停止请求并且开始释放Socket连接。

为什么不能用描述符标识应用程序的入口?

  1. 描述符是和委托创建套接字的 应用程序进行交互时使用的,并不是用来告诉网络连接的另一方。
  2. 客户端也无法知道服务器上的描述符,客户端也无法通过服务器端的描述符去确定位于服务器上的某 一个套接字。〉

Socket连接中大致介绍了协议栈是如何通过网卡完成和目标服务器的连接、断开、收发数据的过程下面按照顺序讲述各个步骤的细节。

下面我们根据上面所讲的各个步骤按顺序进行详细介绍。

创建套接字

首先来看一下创建套接字的情况,下面是协议栈的内容。

image.png

委托分发被拆分为好几个部分,最上面可以看作浏览器,协议栈中主要有两张协议 TCP和UDP, TCP主要是用于和服务器交互收发数据的,UDP则用于较短的控制数据。

IP协议主要控制网络收发操作,主要工作是把一个个拆分的网络包发给通信的目标对象,IP协议包括 ICMP和 ARP协议,前者告知传输过程的错误和控制信息,后者传递以太网MAC地址。

MAC 地址:符合 IEEE 规格的局域网设备都使用同一格式的地址,这种地址被称为 MAC 地址

驱动部分是为了让操作系统能正常使用硬件进行网络收发的一个“适配器”,而所有的电信号最终要通过网卡完成。

套接字和协议栈

协议栈实际上是根据套接字传递的信息来决定做什么操作的,比如发数据要看IP和端口号。

以Windows的套接字为例,直接在CMD中使用 netstat 操作即可:


C:\Users\Xander>netstat -ano
  协议     本地地址             外部地址                    状态           PID
  TCP    0.0.0.0:49666          0.0.0.0:0              LISTENING       604
  TCP    0.0.0.0:49667          0.0.0.0:0              LISTENING       1892
  TCP    0.0.0.0:49668          0.0.0.0:0              LISTENING       4508
  TCP    0.0.0.0:57621          0.0.0.0:0              LISTENING       22748
  TCP    127.0.0.1:1001         0.0.0.0:0              LISTENING       4
  TCP    127.0.0.1:1043         127.0.0.1:1061         ESTABLISHED     8452
  TCP    127.0.0.1:1043         127.0.0.1:1063         ESTABLISHED     8452
  UDP    192.168.159.1:1900     *:*                                    3060
  UDP    192.168.159.1:5353     *:*                                    5248
  UDP    192.168.159.1:58085    *:*                                    3060

netstat 命令 的 ano 三个参数主要用于扩展IP地址端口以及PID的显示,以及一些隐式的可能存在的通信也会被记录。

LISTENING:表示等待对方连接 ESTABLISHED :表示完成连接并且进行数据通信操作

套接字和协议栈和应用程序的交互流程如下:

  1. 协议栈在操作套接字之前,需要事先开辟一块空间来存放用于操作套接字的必要信息。
  2. 协议栈需要向应用程序返回描述符表示当前连接的是哪一个“管道”。
  3. 之后应用程序需要和协议栈交互就必须要携带描述符,不过这样也节省了协议栈了解应用程序要和哪一个套接字交互。

连接服务器

连接的目的是为了让两台不再同一个地方的主机能够相互认识对方,这时候不可避免的需要互相提供自己的信息,这样才能正确的建立连接然后使用套接字传输数据。

连接的含义

人和人之间的沟通有时候可以不使用一个语言,只要双方都听懂就行,但是对于计算机是行不通的。

所以连接操作的控制信息要根据通信规则确定,协议栈在通信之前需要依靠一块空间来存放必要数据,这块内存空间称为缓冲区。

连接需要双方各自告知自己的信息,所以连接最开始的时候是没有任何数据交互的,由于是TCP是全双工的协议客户端和服务器都需要建立套接字,不过双方不知道和谁连接,所以需要在客户端和服务端各自开辟一块空间来存放对方的IP和端口等必要的传输信息。

为了让双方既可以正常通信,又可以根据自己的系统设计协议栈和套接字的控制信息处理方式,网络通信设计采用了 控制信息的的方式让不同计算机和系统能相互认识。

所谓的控制信息可以认为是一种 通用语言,只要是符合这个控制信息规范的头部信息就可以被其他的计算机认识。

控制信息分为两类:

  1. 客户端和服务器的交换的控制信息,主要用于整个通信过程,这些内容在TCP协议进行规定。生活的例子理解是我们和别人通话之前,两边都得知道对方的电话号码和基本身份。
  2. 保存在套接字中用来控制协议栈操作的信息,这些信息主要用来传输数据,通常需要包括通控制信息和数据块,套接字需要通过控制信息了解到发来的是什么类型的数据,然后协议栈才能配合处理数据。

由于在一开始传输的时候是没有具体数据的,通常是一个空的报文头,所以这个控制信息也被叫做 协议头部, 比如下面提到的TCP头部,IP头部。

第一类:TCP 头部格式

image.png

第二类:套接字中的信息

image.png

连接的实际操作

image.png

连接的实际操作主要是调用CONNECT 函数,协议首先会传递给TCP模块,通过TCP模块交换获取控制信息的头部,以此了解具体要连接的套接字信息,然后把头部的SYN比特设置为1,表示可以连接。

TCP 模块处创建表示连接控制信息的头部,接着便把信息传递给IP模块进行委托发送。

三次握手

交换头部信息之后,接着便是常见的TCP三次握手的过程:

  • 第一步:客户端主动打开TCB端口,服务器被动打开TCB端口。发起方携带一个SYN标志,并且携带一个ISN序号Seq=x,但是需要注意的是第一步的过程这个ISN序号是隐藏传递的(因为没有传递数据),因为如果请求不存在数据的交换则不会被显示。客户端发送SYN命令之后进入设置SYN=1,并且设置SYN-SENT(同步-已发送状态)。
  • 第二步:服务器收到客户端TCP报文之后,也将SYN=1,并且回送一个新的ISN序号ack=x+1,并且将ACK=1表示自己收到了,然后在返回参数回送自己新的序列号表示自己的确认请求Seq=y,将状态设置为SYN-RCVD(同步收到)状态,(表示希望收到的序号为xxxx1522),最后也是指定MSS。
  • 第三步:客户端收到服务器的确认报文之后,还需要向服务端返回确认报文,确认报文的ACK=1,并且回传服务器传递的ISN序号+1(ack = y+1),以及自己的ISN序号+1(Seq = x+1),此时TCP连接进入已连接状态,ACK是可以携带数据的,但是如果不携带数据则不消耗序列号。
  • 最后一步:当服务器收到客户端的确认,也进入已连接状态。

image.png

经过三次握手连接建立,直到断开连接之前都可以传递数据。

收发数据

收发数据有两个重点:

  • 第一点是收发数据并不关心数据的格式,而是根据头部信息来辨别是什么类型的数据,对于协议栈来说接收的的内容都是二进制的数据。
  • 第二点是利用缓冲区减少频繁的数据传输提高传输效率。

缓冲区的大小如何控制?

  • 每个数据包的数据长度,协议栈会根据一个叫作 MTU的参数来进行判断,但是MTU指的是总长度,除开头部信息之后获得真实的数据长度MSS
  • 时间,这个时间指的是固定的时间内容不管缓冲区有有没有达到MSS长度必须发送数据的时间,目的是防止等待时间过长造成请求延迟。

名词解释:

MTU:一个网络包的最大长度,以太网中一般为 1500 字节。 MSS:除去头部之后,一个网络包所能容纳的 TCP 数据的最大长度。

但这两个因素实际上并不能完全决定收发数据的效率平衡,TCP协议没有规定协议栈如何平衡,具体需要看操作系统如何决定。

实际上协议栈收发数据是有所保留的,并不是强制按照协议的规定处理,而是给了应用程序一些可控选项,比如浏览器这种要求实时性的应用程序通常不使用缓冲区Http请求拆分

通常情况http的请求响应内容可以通过一个网络包完成,但是针对POST请求等大表单的数据提交则通常会触发TCP拆包操作。

拆包是根据MSS的参数确定的,发送缓冲区会根据这个参数把一个超过一次请求长度的数据拆分为多个包,但是因为实际上同属一份数据,拆分之后所有的数据包都需要添加相同的头部。

注意:TCP是面向字节流的协议,就是没有界限的一串数据,本没有“包”的概念,“粘包”和“拆包”一说是为了有助于形象地理解这两种现象。

image.png

TCP粘包

TCP除了拆包动作之外还包含粘包的操作,所谓粘包是指TCP协议中发送方发送的若干包数据到接收方接收时粘成一个包,从接收缓冲区角度来看后一个数据的头紧接着前一包数据的尾部。

解决粘包、拆包问题策略?

粘包和拆包需要解决容易造成半包读写的根本问题,解决办法也有很多种,主要的策略基本很多网上资料都有讲到,这里直接搬运结论了:

  • 请求消息定长,如果缓冲区不满,则通过补0的方式达到长度,防止粘包和拆包。
  • 在包尾增加回车换行符进行分割,例如FTP协议;
  • 将消息分为头部和消息体,头部中保存整个消息的长度,只有读取到足够长度的消息之后才算是读到了一个完整的消息;
  • 通过自定义协议进行粘包和拆包的处理。(几乎不用)

ACK号确认网络包收发

ACK号码除了在三次握手的过程中确认对方是否有收到请求之外,还能作为判断接收的数据包是否完整的依据,在进行数据传输的时候,接收方会将到目前为止接收到的数据长度加起来,计算出一共已经收到了多少个字节,然后将这个数值写入 TCP头部的 ACK 号中发送给发送方,以表示自己到底受到了多少数据,如果中间存在缺少数据则服务端重新传输即可。

当然仅靠ACK号不能完全作为参考依据,并且只使用ACK号是只考虑 单向传输的情况,但是TCP是全双工协议,无法确定数据接收方来自哪一方。

解决这个问题也很简单,实际在进行双向数据传输的时候双方各自会额外计算一个序号,序号其实就是一组随机数,在接收方收到数据之后每次都需要把序号+1回传给发送方表示自己接收到哪一个序号之前的所有数据。

通过ACK+序号的方式确保数据正确传输,这样可以使得其他网络通信组件不需要额外的失败补偿机制,如果发现丢包或者数据不完整的情况,直接根据序号进行重传重发的操作即可。

image.png

影响数据传输的因素

主要影响因素是返回ACK号的等待时间。

如果ACK号迟迟没有响应给对方服务器,势必会影响整个网络传输的效率,如果下一个数据已经准备好上一个返回包却没有发回去,很容易造成网络的堵塞,对方迟迟拿不到正确结果。

网络环境的复杂多变,这个等待时间不可能是固定的,所以TCP使用了动态时间的方法进行调整,具体的调整方法就是使用滑动窗口

滑动窗口

滑动窗口:指的是在不等待ACK返回结果的情况下直接双方互相不间断的发送数据。

双方需要通过各自的缓冲区顺序返回ACK信息,但是如果无限制的发送数据会导致数据无法处理出现丢包,所以滑动窗口的关键是接收方需要告诉发送方自己最多能接收多少数据

滑动窗口的细节通过一张图更好理解:

image.png

关于接收方的接收量,最大能承受处理多少数据是通过缓冲区大小确定的。另外需要注意下面的图只有单向的部分,实际上对于双向来说都是类似的处理。

影响数据传输的次要因素:返回 ACK号和更新窗口的时机

关于这一点直接记住一个结论,接收方在发送 ACK 号和窗口更新时,并不会马上把包发送出去,而是会等待一段时间,等到其他的通知合并到一起处理,因为ACK号体现的是已经收到的包的数据量,使用这样延迟发送的方式也可以防止过多的更新数据包出现。

最终协议栈收发数据的细节如下:

  1. 协议栈会根据收到的数据块和TCP或者IP头部解析内容,如果确认收到数据则返回ACK + 序号。
  2. 协议栈会把数据块放到缓冲区进行存储,利用滑动窗口的特性按照顺序处理数据交给应用程序处理。
  3. 协议栈会将接收到的数据复制到应用程序指定的内存地址中,然后将控制流程交回应用程序

断开连接

断开连接的部分包含断开连接和删除套接字的操作,断开连接也就是经典的四次挥手的操作,而删除套接字则需要注意在协议栈中并没有规定关闭的时间,但是通常情况下过几分钟之后会删除套接字。

四次挥手端口tcp连接

  • 第一步(客户端):TCP发送释放连接的报文,停止发送数据,释放报文首部,把FIN=1,同时发送序列号,根据上一次传送的序列号+1传送Seq = t + 1(由于下图是在连接之后立马进行四次挥手,所以序列号没有变),此时客户端进行终止等待1的状态。注意FIN不携带数据也需要消耗序列号。
  • 第二步(服务端):服务器回送确认报文,发出确认报文,ACK=1,并且把回传序列号+1回传(ack = t + 1),然后再带上自己的序列号Seq = y,此时服务端进入CLOSE-WAIT状态(关闭等待状态),TCP服务器此时需要停止上层应用客户端向服务端请求释放,处于 半关闭 阶段,此时服务端依然可以向客户端发数据并且客户端需要接收并处理,关闭等待状态意味着整个状态还需要持续一段时间。
  • 第三步(客户端):客户端接收到服务端确认请求,此时客户端进入到FIN-WAIT-2终止等待2的阶段,等待服务器的释放报文。(还有一部分服务器没有发送完的数据需要处理)
  • 第四步(服务端):服务器把最后的数据处理完毕,向客户端发送释放报文,FIN=1,ack=t + 1,由于需要把剩下的数据发送完成,假设处理完成之后需要带上自己的序列号Seq=w,服务器进入最后确认状态,等待客户端确认。
  • 第五步(客户端):客户端收到报文之后,发出确认 ACK=1,ack=w+1,自己的序列号为Seq = t + 1,此时客户端进入到了TIME-WAIT(时间等待状态),此时客户端还是没有释放,必须经过**2 * MSL(最长报文寿命)**之后,客户端撤掉TCB之后才进入CLOSED状态。
  • 第六步(服务端):服务器收到客户端的请求立马进入CLOSE状态,同时撤销TCB,结束此次TCP的连接。(服务端结束TCP连接要比客户端早一些)

image.png

套接字和协议栈和对方服务器的交互流程细节还是比较多的,这里可以发现实际上三次握手和四次挥手实际上只是网络连接当中很小的一部分,最后是从连接服务到数据收发到断开连接的一张简单总结图,建议当作一个大概的流程参考:

image.png

IP和以太网的收发操作

上面的部分比较贴近TCP协议的相关操作,TCP完成连接收发的同时其实都需要IP模块的配合,在了解这两个模块如何配合工作之前需要了解完整的网络包是如何组成的。

包的组成

对于任何一个网络包,都有最外层的抽象概念,那就是头部数据 两个部分

上面的部分有一个这样的图,里面套接字中的TCP数据,这里需要注意在TCP控制信息的前面就是以太网和IP的控制信息,对于只传输控制信息的网络包虽然没有数据的部分,但是可以把协议的头部信息作为数据部分。

通过下面的图也可以发现,所有的网络包必须要委托以太网和IP控制信息才能完成传输。

image.png

把存放数据的网络包进行拆分,可以看到下面的TCP/IP 包结构:

我们可以简单把头部和数据看做是平时的快递,头部是面单,指示从哪里到哪里,然后这个“快递”会通过网络转发设备的查表操作判断传输到那个方向。

转发设备是什么?这里建议看看第一章的关于认识网络传输的基本概念,这里简单提一下:

  • 路由器根据目标地址判断下一个路由器的位置
  • 集线器在子网中将网络包传输到下一个路由

但是实际上集线器和路由器各自有不同分工,集线器负责管理以太网规则传输包设备,路由器管理IP转发规则,所以上面两个步骤也可以做下面的理解:

  • IP协议根据层级规则判断下一个IP转发设备。
  • 子网的以太网协议转发给下一个转发设备。

实际上头部部分应该分为 MAC 头部 和 IP头部。为什么要把头部拆分为两个协议?实际上是为了让协议之间可以实现替换,比如MAC可以替换为局域网、ADSL、FTTH。同时因为互联网这样庞大的网络架构,需要更加细化的分工。

小结

实际上网络包的封装应该范围三个部分:

第一部分是TCP模块组织头部信息和数据包(当然也可能没有数据只有控制信息)。

第二部分是把整个TCP模块塞到IP模块的后面,然后经过网卡发送出去。

第三部分是在IP模块前面加上Mac信息。

image.png

关键:无论要收发的包是控制包还是数据包,IP 对各种类型的包的收发操作都是相同的。

名词解释ADSL:可以理解为以前宽带使用拨号连接互联网上网的方式。

非对称数字用户线路(英语:Asymmetric Digital Subscriber Line)又称非对称数字用户环路Asymmetric Digital Subscriber Loop),简称ADSL。ADSL是一个依靠铜质电话线的数据传输技术比传统的调制器更快。

FTTH:其实就是现在的光纤通信。

光纤到户(英语:Fiber To The Home,缩写:FTTH)是一种光纤通信的传输方法。是直接把光纤接到用户的家中(用户所需的地方)。

这种光纤通信方式及策略与FTTNFTTCHFC(Hybrid Fiber Coaxial)等也不同,它们都是需要依赖传统的金属电线,包括双绞线同轴电缆等,作“最后一哩”的信息传输。

IP 协议头部

IP类似快递上的单号,所以实际上IP模块是无法决定自己选择正确的地址了,哪怕应用程序通过TCP告诉IP发的地址式是一个错误地址,IP也无法自行修正只能照做。

从这样的特点可以看出IP头部又有点类似快递员,和网上买东西商家发错地址或者我们填错地址一样,不能把责任赖在快递员上。

IP协议头部的组成类似下面的结构,注意IP地址的长度固定需要32Bit的空间占用。

image.png

这里需要注意“发送方的IP”地址不是指计算机的IP,而是指网卡对应的IP,因为IP不是分配和计算机而是网卡的,当一个计算机有多个网卡就会存在多个IP。

那么应该如何判断包发送给哪一个网卡?这里涉及到IP协议规则,无论是路由器的转发还是协议栈的处理都需要按照IP协议转给下一个用户。

查询分配给哪一个网卡在不同操作系统中的查询方式不同,查询发送端需要查询是哪个网卡把包发给了路由器,这个动作只需要简单的根据路由器IP地址和网卡的IP进行比对。

在windows中可以通过命令route print 查看路由信息。

获取IP和网卡之后,还需要知道包所属的协议,委托内容是固定的,比如TCP模块就是06,UDP就是17,大部分请求都是HTTP,使用TCP的方式传输。

以太网Mac头部

TCP/IP模块只能在传输层上互相了解,但是往下的链路层以太网用同样的规则是行不通的,所以头部加上TCP/IP的头部之后,还需要在头部加上Mac头部,Mac头部包含了发送方和接收方的Mac信息,这里可以简单理解为Mac和IP的作用类似,不过Mac头部是48Bit,而IP头部是32Bit。

需要注意以太类型就是Mac包装的后面的真实数据的类型, 如果是IP就是IP协议。另外需要注意在发送Mac包给接收方之前,由于不知道对方的Mac地址,所以还需要一步查询操作。

注意IP 模块根据路由表 Gateway 栏的内容判断应该把包发送给谁。

下面是Mac头部的组成:

image.png

查询Mac地址

查询对方的Mac地址需要用到ARP( Address Resolution Protocol,地址解析协议),ARP通过广播的方法查找到目标地址,所谓广播就是字面意思把消息发给所有的其他互联网用户,等待对方应答。

为了防止每次查询都要带ARP的数据,所以有一块ARP的缓存专门缓存这个地址,但是需要注意这个缓存和IP模块的IP地址一样,过一段时间会被ARP缓存淘汰掉,但是如果IP刚刚变化可能会导致ARP缓存未及时更新导致网络异常。

实际整个工作都是由IP模块完成的,虽然Mac地址是以太网数据传输的必要内容,但是实际上让IP模块负责这些工作是有利的。

为什么需要以太网?

# 有了 IP 地址,为什么还要用 MAC 地址?

以太网基本知识

首先来看看以太网的基本发展,虽然设计结构越来越精细,但是本质上干的活却没有发生变化。

以太网早期原型本质上可以看作是一根网线以及一个用于收发的设备,网络信号发送之后通过广播最终到达所有设备,在开头的收发信息让其他人可以知道信息最终要发给谁,在Mac头部就包含了“收货地址”,而具体发送了什么类型的可以通过上面的“以太类型”进行判断。

以太网在后续的发展中将主干网线替 换成了一个中继式集线器,收发器变成双绞线,虽然形式变了,但是本质的工作没有变。

以太网到了现代最终由交换式集线器完成所有的操作,并且网络请求只有请求方和接收方可以互通,集成度增加以及网络传输安全性能增加。

但是以太网无论怎么发展性质始终没有任何变动:

MAC 地址代表的目的地,用发送方 MAC 地址识别发送方,用以太类型识别包的内容。

image.png

IP模块转光(或电)信号

网络信号发送依赖网卡,但是网卡并不是插上电就可以使用的,还需要依赖初始化以及驱动程序才能完成操作,驱动程序和初始化操作在其他很多电脑硬件中比较常见,但是以太网有比较独特的驱动操作,那就是控制以太网收发操作的MAC当中收发MAC地址。

另外网卡还有一个特性是网卡的 ROM 中保存着全世界唯一的 MAC 地址,这是在生产网卡的时候就已经决定。

所以可以看到最终完成IP数据转化的关键是驱动程序,网卡中保存的 MAC 地址会依赖网卡驱动程序读取并分配给 MAC模块。

网络包的控制信息

MAC模块工作在网卡调用MAC包发送请求命令之后,MAC模块的工作是划分网络包的“边界”。

image.png

为了划分边界,MAC模块会加上三个控制信息:

  1. 报头:是一串像 10101010…这样 1 和 0 交替出现的比特序列,长度为** 56 比特**,它的作用是确定包的读取时机
  2. 起始帧分界符(SFD):确定帧的起始位置,主要是辅助电信号切分报文头部和真实的网络包边界,并且判断出每个比特的界限。
  3. FCS:检查包传输过程中因噪声导致的波形紊乱、数据错误,它是一串 32 比特的序列,是通过一个公式对包中从头到尾 的所有内容进行计算而得出来的

响应内容传输从IP给TCP

当服务器接收到网络包之后,首先协议栈会判断以太网头部的以太类型,发现是0800为TCP/IP协议,接下来是IP模块工作,首先是检查IP头部是否正确,IP地址是否正确。

如果接收方是window客户端,因为不会对包进行转发,如果发现包不是发给自己的,会调用ICMP消息回传给请求发送方,IMCP的消息格式如下:

image.png

另外接收到的网络请求可能会因为数据包过大出现IP分片,分片的包会在 IP 头部的标志字段中进行标记,IP模块会把分片过的包暂存内部内存空间,等相同ID的包全部接收到缓冲区之后再拼接。

怎么保证拼接的顺序正确呢?可以查看前文IP 头部还有一个**分片偏移量(fragment offset)**字段,它 表示当前分片在整个包中所处的位置。

IP模块完成数据分片重组之后,数据包交给TCP模块操作,TCP还会再次检查一遍请求方和接收方的IP信息,以及获取端口号找到对应的套接字,找到套接字之后根据应用程序的类型进行不同的操作,这个过程可能是建立连接,也可能是完成应用程序数据的读写操作。

这里可能会觉得IP检查不是IP模块的操作么,TCP去看IP模块的信息是不是“越权”了?实际上这是一种性能开销都考虑而违反“迪米特法则(Law of Demeter)”的一种特例。因为TCP模块需要频繁使用IP模块的信息,如果老是需要数据之间的交互传输非常影响性能。

UDP协议收发操作

TCP/IP为了保证数据准确收发需要使用一系列复杂的模块和过程配合保证数据的完整传输,但是有时候有些应用程序为了保证高效会舍弃使用TCP这种复杂的机制。

UDP协议的要点是尽可能将所有的数据通过一个包解决,UDP 没有 TCP 的接收确认、窗口等机制,因此在收发数据之前也不 需要交换控制信息。UDP的实现非常简单只需要应用程序加入头部,直接交给IP模块完成即可,接收方也只需要检查IP头部的发送方和接收方的IP地址信息,然后再从UDP找到端口号,最后再找到套接字信息把数据给应用程序。

因为UDP不保证传输的稳定性所以无论包是否接收到都无关紧要,只要对方没有回应直接把包进行重发即可。这种不需要保证传输稳定性的场景还是有不少的,比如聊天数据、音频和视频信息,即使丢失一点点也没有关系,最多是卡顿一下而已。

关键:UDP 可发送的数据最大长度为 IP 包的最大长度减去 IP 头部和 UDP 头部 的长度。一般来说 IP 头部为 20 字节UDP 头部为 8 字节,因此 UDP 的最大数据长度为 65507 字节。

下面是UDP的头部信息:

image.png

小结

在第二章我们了解Socket链接的步骤和大致细节,另外介绍了整个互联网比较重要的两个协议TCP协议和IP协议,在两个协议中需要重点掌握头部设计,IP模块完成TCP模块的数据,TCP数据封装应用程序数据,之后还需要配合Mac以太网模块完成网络包的最后封装,等一切准备工作完成之后,由网卡以及驱动程序把整个包发送出去,所以其实可以看到决定你能不能上网等实际上是网卡和驱动(这不是废话),但是这些内容属于不同层级的内容,需要一一消化。

介绍了TCP之后,在在第二章最后部分简单提到了UDP协议,UDP是一种简单暴力的协议,设计的目的是让所有的数据尽可能通过一个包完成,所以他不需要链接也不需要保证数据安全传输,数据丢了直接传输即可,UDP的应用也是十分广泛的,比如游戏,视频,音乐等等数据的传输,很多时候丢一点根本无关紧要,因为即使找回来这些数据也没有意义。

TCP/IP连接也只是互联网数据传输的一小部分,但是却是最为核心的部分,虽然往下还有以太网和网卡以及网络通信如何上网等细节,但是只有深刻了解TCP/IP协议才能了解整个互联网是如何交互和数据传输的。

《网络是怎么样连接的》读书笔记 - 集线器、路由器和路由器(三)

本章重点

  1. 信号如何在网线和集线器中传输?如何抑制信号传输中的失真情况?
  2. 交换机的作用和工作方式是什么?
  3. 路由器包转发的细节,以及和交换机的区别。
  4. 路由器额外功能了解,不仅仅是接入互联网的媒介,还包含许多其他功能。
  5. 了解集线器、路由器、交换机在OSI模型(TCP/IP模型)的位置。

集线器和网线信号传输

如果了解[[《网络是怎么样连接的》读书笔记 - ADSL]]和[[《网络是怎么样连接的》读书笔记 - FTTH]]两个部分的内容,应该清楚网络包在传输的过程中最终转化为电信号或者光信号传输,我们通常所说的TCP协议、IP协议、以太网等等实际上都已经被“屏蔽”的。

最终包的传输只是一个转发设备到另一个转发设备信号传输,所有的网络包都相当于一个独立的快递一般进行传输。

这个传输过程涉及到本章的三个最重要的内容,也就是集线器,交换机,路由器,整个传输的过程和下面的内容类似:

image.png

防止信号衰减

所谓的以太网信号实际上可以看作是正负变化的电压,网卡的PHY模块负责完成正负电子信号电路输出。

信号传输的根本性的问题是网线越长,信号衰减和损耗越严重。由于以太网是使用方波信号传输,高频信号容易丢失,这样容易导致信号的失真,另外线路噪声条件无论好坏都有可能导致信号失真,所以问题很显然是在传输材料上。

互联网最早使用的是双绞线,所谓双绞线是最早期的ADSL的接入互联网而使用的电话线和网线混合的模式诞生的一种特殊设计模式。

而最早的以太网使用专用同轴网线,后来变成由美国室内电 话线改良的版本,原因是它可以兼容电话线的布线工具和材料, 比较方便。

想要双绞线如何避免信号失真和噪声问题,我们需要了解噪声是怎么来的,这里需要介绍一点物理知识:

信号噪声来自于网线周围的电磁波,影响网线信号传输的电磁波主要有两种,第一种是液晶显示设备泄漏的电磁波,第二种是相邻的网线产生的电磁串扰,信号传输依靠的是电流,电流在经过网线周围周围就会产生电磁波,网线之间的电磁波干扰被称为串扰

要解决上面两种电磁波的问题,通常有下面的方式:

  1. 第一种通过双绞的方式让电流通过不同的方式以螺旋的方式传输,其中两根信号线中产生的噪声电流方向就会相反,这时候信号依然可以正常传输,但是噪声得到了控制。
  2. 第二种电磁串扰问题可以通过绕线的方式来解决,由于绞线之间本身就有十分规律的间隙,正反信号之间的距离通过缠绕的方式进行抵消,所以哪怕相邻只要互相缠绕方式正确就可以让噪声进行抵消。

所以网线螺旋缠绕方式本身是有讲究的,既可以解决电流本身掠过其他电磁波设备产生的噪声,又可以防止不同网线交叉的电流产生的电磁波噪声。

集线器工作

信号传递到整个网络之后将会广播到整个网络,在第一章“以太网MAC头部”当中介绍了MAC地址中包含了接收方的“收货地址”,集线器负责以太网架构中对于信号进行广播的角色。实际上可以想象是接收一端网卡传递的电信号,然后通过网线传递给另一端。

我们可以观察集线器的设计,PHY模块的功能基本是相同的,注意这里的接线方法是交叉连线的,使用直接连接的方式是无法接收信号的。

如果集线器不想和某个网卡通信则需要一个中间媒介完成切换的动作。

RJ45接口:通常用于数据传输,最常见的应用为网卡接口。 RJ45是各种不同接头的一种类型;RJ45头根据线的排序不同的法有两种,一种是橙白、橙、绿白、蓝、蓝白、绿、棕白、棕;另一种是绿白、绿、橙白、蓝、蓝白、橙、棕白、棕;因此使用RJ45接头的线也有两种即:直通线、交叉线

image.png

为了让不同的接口实现“接入”和“关闭”的操作,需要依赖MDI/MDI-X 切换开关,如果存在这个开关的则可以切换MDI/MDI-X 模式,集线器直接的连接可以都改为MDI 模式(也就是直连模式)。

但是如果需要和其他计算机的网卡交互,需要切换为MDI-X 模式进行交互,另外注意不是所有的集线器都有切换开关,所以如果某个集线器只有MDI-X 接口,也可以通过默认的MDI- X接口完成交叉交互。

这里可能有点难以理解,所以换一种解释:我们知道电流是从正极流向负极,所以在集线器和两个计算机的网卡交互的时候是需要进行“发送端”和“接收端”的正反交叉连接。

而集线器的设计由于是“平行设备”,可能存在只支持正反信号交互或者直接连接的方式完成交互,所以需要模式的切换开关进行兼容,但是如果集线器只有正反信号的交互接口,则直接通过交叉交互连接的方式完成信号交流。

image.png

现在我们再看看另一端接收内容拼接成一个完整的结构图,和前文所说的一样在网卡的这一端。

image.png


《网络是怎么样连接的》读书笔记 - 汇总篇(二)https://developer.aliyun.com/article/1395010

相关文章
|
3月前
|
传感器 运维 物联网
蓝牙Mesh网络:连接未来的智能解决方案
蓝牙Mesh网络:连接未来的智能解决方案
363 12
|
3天前
|
负载均衡 网络协议 算法
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
这网络层就像搭积木一样,上层协议都是基于下层协议搭出来的。不管是ping(用了ICMP协议)还是tcp本质上都是基于网络层IP协议的数据包,而到了物理层,都是二进制01串,都走网卡发出去了。 如果网络环境没发生变化,目的地又一样,那按道理说他们走的网络路径应该是一样的,什么情况下会不同呢? 我们就从路由这个话题聊起吧。
18 4
不为人知的网络编程(十九):能Ping通,TCP就一定能连接和通信吗?
|
1月前
|
物联网 5G 数据中心
|
2月前
|
Docker 容器
docker swarm启动服务并连接到网络
【10月更文挑战第16天】
45 5
|
2月前
|
安全 网络架构
无线网络:连接未来的无形纽带
【10月更文挑战第13天】
77 8
|
2月前
|
存储 网络协议 Java
【网络】UDP回显服务器和客户端的构造,以及连接流程
【网络】UDP回显服务器和客户端的构造,以及连接流程
60 2
|
2月前
|
人工智能 安全 搜索推荐
|
2月前
|
监控 安全 5G
|
2月前
|
安全 5G 网络安全
5G 网络中的认证机制:构建安全连接的基石
5G 网络中的认证机制:构建安全连接的基石
166 0
下一篇
DataWorks