计算机网络知识点

295 阅读21分钟

物理层

物理层传输的都是电信号了, 也就是高低电平

通信方式

单工: 同一根传输线只能单向传输

半双工: 同一个根传输线同一时刻只能单向传输, 例如t1时刻A->B, t2时刻可以B->A

全双工: 同一根传输线同一时刻可以双向传输

链路层

链路层主要在两个客观存在的物理设备之间传递mac帧, 链路层一定是通过一个个节点通信的.

mac地址是什么?

长度6字节(48位), 是网络适配器(网卡)的唯一编号, 可以理解为网络世界的身份证号码

一台主机有几个mac地址?

mac地址和网络适配器一一对应, 一台主机有几个网络适配器, 就有几个mac地址

mac帧

mac帧头部14个字节

将IP数据报添加上头部和尾部, 封装成mac帧, 头部中包含了源mac地址(当前物理设备的)和目标mac地址(相邻的物理设备的), 这里的mac地址指的的此次传输两个相邻设备的mac地址.

数据部分是ip数据报, 对于不同网络中数据部分的长度要求不同, 例如以太网是1500字节, 点到点是296字节, 等等, 这部分会在传递给数据链路层的时候就划分好

异构网络

链路层存在各种各样不同的网络结构, 比如以太网、令牌环网等, 异构网络是由不同制造商生产的计算机,网络设备和系统组成的,大部分情况下运行在不同的协议上支持不同的功能或应用。异构网络之间需要通信, 需要借助交换机,路由器或者网管等设备

同一网络

同一网络之间如果知道源mac和目标mac地址的话, 就是直接通信mac帧的, 不需要经过别的节点

链路层的节点有哪些

一般就是主机本身和具有交换功能的设备(例如交换机, 路由, 网关)

主机是如何知道下一步mac地址的?

主机本身无法直接查找到下一节点的mac地址, 需要通过ip地址来获取mac地址.

arp协议

实现由ip地址得到mac地址.

当前主机一定知道目标IP地址, 但是不一定知道到达目标Ip的下一步mac地址. 首先当前主机根据目标ip地址可以判断得到目标ip是否在同一网段, 即是否在同一网络中, 如果在, 那么查找arp缓存, 根据目标ip得到目标mac地址, 如果缓存中没有, 发送arp广播请求, 目标主机受到广播后会发出应答, 告诉当前主机mac地址. 如果目标ip不在同一网段, 当前主机就会通过arp协议获得当前网络网关或者路由器的mac地址, 然后传递到下一个网络, 重复该过程.

网络层

IP协议的作用?

ip协议将数据链路层不同的异构网络连接起来, 使得好像只有一个网络一样. 也就是IP协议是所有异构网络都支持的, 因此可以通过ip协议将所有网络连接起来.

Ip报文的格式

20字节的首部, 包含目标ip和源ip, 数据部分根据所处网络的不同(不同网络能够在数据链路层传递的mac帧的大小不同)会进行分片. 数据部分是传输层的报文数据(TCP或UDP)

IP地址的组成

ip协议会将所有网络连接, 对外表现成同一个网络,一般称为公网, 那ip地址就是在同一个网络中的身份标示.因此ipv4随着公网入口的增多, 逐渐不够用了, 才需要ipv6

ipv4

32位二进制, 分成四个字节, 每个字节用.隔开, 通常使用的时候, 每个字节都用10进制数表示, 每个字节的10进制范围就是0-255, 叫点分10进制表示法.

ipv4 ip地址由网络地址 + 主机地址, 网络地址相同, 表示在同一网络中

子网掩码

通过子网掩码, 就可以知道哪些位是网络地址, 哪些是主机地址, 子网掩码不能单独存在,它必须结合IP地址一起使用。子网掩码只有一个作用,就是将某个IP地址划分成网络地址和主机地址两部分。

ipv6

128位二进制, 16位二进制为一段, 一共8段, 每段之间用:隔开, 通常用4位16进制数表示一段.

ipv6也是由网络地址 + 主机地址组成 但是ipv6中没有子网掩码了, 但是是采用前缀的形式表示

例如234e:0:4567::3d / 64 后面的64就表示前64位是网络地址

vpn

本身局域网指的是在同一地域搭建的网络, 局域网内部的主机通信是不经过公网的

但是vpn是虚拟专有网, 假设公司在A城市有一个局域网R1, 在B城市有个局域网R2, 两个局域网中所有主机的ip都是按照局域网分配的, 此时R1的主机如果想和R2通信, 其实是使用R1的公网ip, 和R2的公网ip进行通信传输的, 但是对于主机来说, 感知不到这一点, 似乎仍旧是在访问局域网, 因此叫虚拟专有网, 感觉也可以叫虚拟局域网更好理解

同时这种方式也节约了公网ip, 对外统一使用一个(或者多个)公网ip, 对内互相使用局域网ip

nat协议

网络地址转换, 在vpn中, 就需要把局域网中的地址转成成公网ip, 需要有个映射规则, nat就是完成这个功能的, 当一个局域网拥有n个公网ip的时候, 同一个局域网内只能同时有n台主机, 通过nat得到公网ip, 然后访问公网, 但是napt技术, 利用端口号, 使得局域网内的多台主机可以使用同一个公网ip进行访问(一般公司就是这种)

通过nat和napt大大减少了专有网络对于公网ip的消耗.

生活中哪些使用了vpn和nat

例如公司一般都是只有一个公网ip, 或者是家里也只有一个公网ip, 但是会有很多台设备同时上网

传输层

TCP

只支持1对1的连接.

tcp报文格式:

20字节首部, 包含源端口号和目标端口号, 后面是数据部分

三次握手

代表三次交互, 也就是三个请求

三次握手的目的, 是因为tcp连接本身有重试机制, 如果客户端发送的第一个连接在一定时间内没有受到确认返回, 会第二次发送连接请求, 此时如果第一次的连接请求到达了, 需要保证第一次连接不会被建立, 而只建立第二次的连接请求. 因此才有了第三次握手.

第一次握手: 客户端向服务端发送连接请求

第二次握手: 服务端同意并返回确认

第三次握手: 客户端收到确认(如果只是为了建立连接, 二次握手其实就足够了, 但是为了防止无效连接, 需要第三次握手), 客户端继续向服务端发送确认(如果是失效连接, 客户端本身是知道的, 就不会发送确认了).

最后服务端得到确认, 建立连接.

四次挥手

代表四次交互, 也就是4个请求

四次挥手, 是A和B建立TCP连接, 某一方需要断开连接, 但是另一方可能还处于数据传输的状态, 因此挥手需要更多次的交互.

第一次挥手: A自己不需要TCP连接, 向B发送连接释放的请求.

第二次挥手: B收到后, 向A发送确认, 不再接受A传输的数据, 此时的TCP连接只能B向A发送数据, A不能再向B发送. (需要B确认的A才不发送的原因是因为, B有可能还没有收完数据, 此时可能还需要A重传)

第三次挥手: 当B不再需要传送时, 向A发送释放连接的请求

第四次挥手: A回复确认, 等待一个TTL(报文最长生存周期, 2ms)后, 才断开连接(这是因为B可能是在发送完最后一个报文后, 立刻通知A断开连接, 此时报文还没到达A, 因此A需要等待才能断开). B在收到A的确认后, 就可以立刻断开连接

可靠传输:

TCP的可靠传输, 靠着报文的超时重传来实现, 一个报文在发送一段时间后, 如果没有收到确认, 那么就会重传这个报文段.

流量控制(滑动窗口):

TCP通过滑动窗口来控制报文传输, 发送方和接受方都拥有一个窗口, 发送方的窗口大小根据接受方的窗口大小来制定(因此接受方可以通过控制窗口大小, 来控制发送方的发送速度).

TCP报文段的发送和确认

TCP报文会拆成一个个报文段, 里面有序号, 维持顺序, 将所有报文发送出去后, 到达接受段段报文段不一定是按照顺序到达的, 因此接受段在每次收到报文后会回复确认, 但是需要注意的是, 接受端回复确认并不是说我收到了3, 我收到了6这样的, 每次回复的是到达报文有序排列后, 最后一个有序的序号, 例如接受端收到了1, 2, 3, 7, 8 那么在收到6的时候会回复3, 在收到9的时候也会回复3. 因此回复的时机就是在有报文到达的时候.

拥塞控制

如果网络状况良好, 那么发送发和接受方的发送情况只受滑动窗口大小的限制, 但是如果网络状态不好, 就会有大量的报文需要重传, 就会导致网络拥塞, TCP通过四种方式来避免这种情况, 这四种策略是同时生效的

慢开始

发送方一开始只发送一个报文, 收到确认后, 下次就发送两个, 以此类推. 每次成功传输就一次翻倍, 如果出现超时, 重复慢开始的过程, 重新开始发送一个报文, 二个..

拥塞避免

设置一个门限, 如果超过门限, 那么每次只多发送一个报文, 如果出现超时, 门限变为原来的一半

快重传

假设一个报文分成M1, M2, M3, M4, M5, M6, M7几段, 此时如果接受段回复了三次M2, 那么表示M3一直没到(M1, M2已经到了, M3之后的报文也到了两个了), 此时不会等待M3报文的超时结束, 而是直接重传M3, 相当于节省了等待时间

快恢复

一旦发生快重传, 此时其实认为M3已经超时了, 但是并不需要直接调整为慢开始, 而是每次发送的数量回滚到上个阶段(如果当前是发送8, 现在就回滚成发送4个)

UDP

无连接的, 无拥塞控制, 尽可能多的传输报文, 不具有可靠性, 支持1对1, 1对多, 多对1, 多对多的传输.

udp报文格式: 20字节首部, 包含源端口号和目标端口号. 数据部分为需要传输的数据

应用层

DNS

域名解析协议, 可以根据域名解析成ip地址. 53端口号

DNS在解析过程中的通信通常是UDP, 某些情况也是TCP

FTP

文件传输协议, 建立TCP连接传送文件, 21端口号

一个web请求的整体流程

http协议是基于tcp/Ip的, 因此一个http请求, 报文会被组织成 mac数据头 + Ip数据头 + TCP数据头 + http数据报文.

宏观上来说,  Http会通过TCP建立起一个到服务器的连接通道,当本次请求需要的数据完毕后,Http会立即将TCP连接断开,这个过程是很短的。所以Http连接是一种短连接,是一种无状态的连接。所谓的无状态,是指浏览器每次向服务器发起请求的时候,不是通过一个连接,而是每次都建立一个新的连接。

微观上来说从传输层到链路层, 报文的传递在每个节点都会经历报文的拆解和拼装的过程. 一段报文到达某个节点, 首先会拆开最外层的mac数据头, 判断mac地址是否是当前节点, 如果是拆开ip数据头, 比较目标ip是不是当前ip, 如果是, 继续拆包, 如果不是, 通过arp协议, 得到下一个节点的mac地址, 不修改ip数据包的内容, 将本机mac和下一节点的mac地址, 封装成新的mac数据头, 添加到报文到, 将报文发送出去.

http协议

http 请求

请求分为三个部分: 第一部分为请求类型 + url + 协议版本 用空格间隔 GET www.example.com/ HTTP/1.1

第二部分为header里的内容, 每一个key-value对为一行 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cache-Control: max-age=0 Host: www.example.com

第三部分为内容主体, 和上文的header用空行隔开

param1=1&param2=2

http 响应

响应分为三部分: 第一部分为协议类型 + 状态码(http协议中的, 而不是自己定义的) + 响应描述 HTTP/1.1 200 OK

第二部分为响应的header内容, 每个key-value键值对为一行 Connection: keep-alive Content-Encoding: gzip Content-Length: 648

第三部分为内容主体, 和上文的header用空行隔开

URI(URL)

URI是统一资源标示符, 也就是说可以在一定范围内, 唯一的标记某个资源, 也就是这个资源的一个唯一编号, 但我们无法通过这个编号找到这个资源在哪. URL是统一资源定位符, URL能唯一的定位一个资源, 通过URL我们就能找到这个资源

URL是URI的子集, 就是说URI也可以有用来定位的标示符, 但是为了区分, 一般区别记忆

常见状态码

200 成功 301 302 重定向 403 请求被拒绝 404 找不到页面 500 服务器异常

短链接与长连接

短链接就是每一次http交互, 都建议一个tcp连接, 交互结束立马断开 长连接就是浏览器和服务器建立一次tcp连接, 可以进行多次http交互. 但是长连接是有顺序的, 必须等第一个请求完毕后, 第二个请求才能通过这个连接通信

http 1.1 之前, 默认短连接, 如需长连接通过Connection : Keep-Alive http 1.1 之后 默认长连接, 如需断开连接, 需要显式的提出

http是无状态的

http协议是无状态的,每个请求是独立的, 每个http都包含了通信所需要的所有信息.

而有的协议是有状态的, 例如SMTP协议,它的第一条消息必须是HELO,用来握手,在HELO发送之前其他任何命令都是不能发送的;接下来一般要进行AUTH阶段,用来验证用户名和密码;接下来可以发送邮件数据;最后,通过QUIT命令退出。可以看到,在整个传输层上,通信的双方是必须要时刻记住当前连接的状态的,因为不同的状态下能接受的命令是不同的;

无状态主要是为了让HTTP协议尽可能简单,使得它能够处理大量事务

cookie和session

cookie保存在浏览器, 每次请求服务端的时候带着cookie, cookie就包含了信息本身, 服务端解析即可使用

cookie就是指的header里的一个k - v键值对.

session保存在服务端, 浏览器在请求的时候带上sessionId, 这本身不是信息, 只是一个标记, 服务端收到sessionId后, 自己查询对应的内容, 得到信息后, 进行后续操作

项目是如何设计登录的

用于验证由node层完成, 登录验证都由前端来控制.利用session做的

正向代理, 反向代理

正向代理就是A作为用户, 在访问C的时候, 必须经过B, A是知道这个情况的, 例如在使用VPN的时候, 我们自己知道是请求先到达的代理服务器. 是有意识的通过代理服务器进行访问 反向代理就是A作为用户, 我知道我要访问C, 我的目标也是C, 但是C可能会把请求转交给D处理, A根本就不知道D的存在, 此时C就是反向代理

https

http是明文传输, 通信双方本身是不受协议验证的(当然你可以通过请求里的内容进行校验 JWT等), http请求可能会被拦截篡改等问题. 使用https可以解决上述问题: https = http + ssl证书 通信时客户端先通信时 先通过SSL证书的验证, 再进行通信

SSL证书验证 + 数字签名

证书验证是非对称加密 (1) 浏览器发送https请求 (2) 服务端返回证书(包含公钥) (3) 浏览器验证证书, 验证成功后, 生成一个随机数, 利用公钥加密, 传给服务端 (4) 服务端利用私钥解密, 得到这串随机数

数据传输

数据传输是对称加密 随机数算是两方都知道的私钥 (1) 服务端利用浏览器传来的这串随机数做对称加密. 返回给浏览器 (2) 浏览器利用本地记录的随机数解密, 得到数据 (3) 这一次https建立的TCP连接, 之后的数据都通过这个随机数做对称加密.

摘要加密

报文摘要:用于对发送的报文生成一个非常小的摘要信息。这个摘要信息保证原报文的完整性,即原报文只要有一位被改变,则摘要信息就会不匹配。 https还有对报文内容进行摘要加密的功能, 也就是对实际内容挑选出部分进行加密传输, 一旦被篡改, 因为篡改者不知道私钥, 无法再次生成加密摘要.

MD5

计算机安全领域广泛使用的一种散列函数,用以提供消息的完整性保护。

MD5加密后如何解密

MD5加密后无法解密, 因此可以用来做报文摘要, 在验证的时候只需要对内容同样求MD5值, 就可以知道报文是否被篡改了.

公钥加密 私钥解密的逻辑

首先强调目的: 这种方式的目的是为了防止传输的信息泄漏(即发送者发送的信息一定不会被别人得到内容)

缺点: 接受者无法防止收到错误的信息

发送者拥有公钥, 对某个数据用公钥加密后传输

接受者拥有私钥, 只有私钥解密后才能得到正确的信息. 但是接收者无法验证这个信息是不是正确的人发送的.

私钥签名 公钥验证(也就是JWT采用的方式)

首先强调目的: 这种方式的目的是为了验证发送者的身份的. 因此签名的内容肯定不是传输的数据本身 发送者拥有私钥: 签名的主体是A, 私钥加密后是B, 期望传输的数据是C, 传输的时候A, B, C都要传送 接收者拥有公钥: 接收者利用公钥解密B, 发现内容确实是A, 就验证了发送者的身份, 同时C数据是可信的

对称加密和非对称加密的概念

对称加密

只有一把钥匙, 加密和解密都是用同一把钥匙.

非对称加密

有两把钥匙, 一把加密另一把解密

JWT

json web token 通过私钥, 可以验证通信双方的身份(通过私钥加密, 验证签名的方式), 但是对于请求劫持, 没有办法.

身份验证

客户端需要维护公钥和私钥, 服务端也是维护公钥和私钥, 然后客户端加密的时候用私钥, 但是公钥带到参数中, 告知服务端, 服务端就能决定应该使用哪个私钥.

然后就可以验证客户端是不是真的是这个公钥对应的私钥.

传输用户登陆信息

对用户的登录信息进行saltMd5加密成一个sign, 每次请求的时候带着这个sign, 服务器通过私钥验证.

saltMd5

我们知道,如果直接对密码进行散列,那么黑客可以对通过获得这个密码散列值,然后通过查散列值字典(例如MD5密码破解网站),得到某用户的密码。

  加Salt可以一定程度上解决这一问题。所谓加Salt方法,就是加点“佐料”。其基本想法是这样的:当用户首次提供密码时(通常是注册时),由系统自动往这个密码里撒一些“佐料”,然后再散列。而当用户登录时,系统为用户提供的代码撒上同样的“佐料”,然后散列,再比较散列值,已确定密码是否正确。

  这里的“佐料”被称作“Salt值”,这个值是由系统随机生成的,并且只有系统知道。这样,即便两个用户使用了同一个密码,由于系统为它们生成的salt值不同,他们的散列值也是不同的。即便黑客可以通过自己的密码和自己生成的散列值来找具有特定密码的用户,但这个几率太小了(密码和salt值都得和黑客使用的一样才行)。

htpp 2.x

(1) 多路复用: 本身http就算建立长连接, 请求也是按顺序的, 一个请求完毕才能进行下一个, http 2.x中, 在一次tcp连接中, 客户端和服务端可以同时发送和接受多个请求, 相当于是并发, 避免了被某个慢请求阻塞的情况(当然理论上总时间不会明显变少, 只是会减少阻塞).

(2) header复用: 同一连接的不同请求中, header大部分情况下内容都是重复, 因此对于重复的内容不再重复传输(重复的内容由客户端和服务端在自己那里维护, 除了第一次, 每次只需要传输相应标记(比如字典中编码)即可, 而不需要传递真正的内容), 同时对header的内容也进行霍夫曼编码, 减少传输量

(3) 推送资源: 那么正常情况下,为了展示页面需要发 3 次请求:

发起 1 次请求 index.html 页面 解析 index.html 页面发现 style.css 和 something.png 资源,发起 2 次请求获取资源。

如果服务端配置了服务端推送之后,那么情况变成下面的样子:

浏览器请求 index.html。 服务器发现浏览器请求的 index.html 中包含 style.css 和 something.png 资源,于是直接 index.html, style.css, something.png 三个资源都返回给浏览器。