跳转至

网络知识

参考1 参考2

1 HTTP(HyperText-Transfer-Protocol)

1.1 HTTP协议格式

HTTP的请求和响应的消息协议是一样的,分为三个部分,起始行消息头消息体。这三个部分以CRLF作为分隔符。最后一个消息头有两个CRLF,用来表示消息头部的结束。 1. HTTP请求的起始行称为请求行,形如GET /index.html HTTP/1.1 2. HTTP响应的起始行称为状态行,形如200 ok 3. 消息头部有很多键值对组成,多个键值对之间使用CRLF作为分隔符,也可以完全没有键值对。形如Content-Encoding: gzip 4. 消息体是一个字符串,字符串的长度是由消息头部的Content-Length键指定的。

客户端报文示例

GET /hello.txt HTTP/1.1
User-Agent: curl/7.16.3 libcurl/7.16.3 OpenSSL/0.9.7l zlib/1.2.3
Host: www.example.com
Accept-Language: en, mi

服务端响应报文示例

HTTP/1.1 200 OK
Date: Mon, 27 Jul 2009 12:28:53 GMT
Server: Apache
Last-Modified: Wed, 22 Jul 2009 19:15:56 GMT
ETag: "34aa387-d-1568eb00"
Accept-Ranges: bytes
Content-Length: 51
Vary: Accept-Encoding
Content-Type: text/plain
GET、HEAD请求没有消息体,POST、PUT请求有消息体

1.2 http状态码

状态码 状态码英文名称 中文描述
200 OK 请求成功。一般用于GET与POST请求
301 Moved Permanently 永久性重定向。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI。今后任何新的请求都应使用新的URI代替
302 Found 临时性重定向。与301类似。但资源只是临时被移动。客户端应继续使用原有URI
304 Not Modified 极少人知道这个错误,因为大部分后端开发者的前端Javascript开发经验都严重不足。当你用Chrome打开一个经常访问的网站,看看Network传输的静态资源就可以看到很多304状态码。它表示该资源被浏览器缓存了不需要重新请求服务器。
400 Bad Request 用于参数验证,少了一个参数或者参数类型错误之类的。
401 Unauthorized 权限不足,这个很好理解,就是资源存在但是不让你访问。
403 Forbidden 资源禁止访问,如果你的IP列为黑名单了,就会发生这种错误。
404 Not Found 服务器无法根据客户端的请求找到资源(网页)。通过此代码,网站设计人员可设置"您所请求的资源无法找到"的个性页面。也可以在服务器拒绝请求且不想说明理由时使用
500 Internal Server Errorv 服务器内部错误,无法完成请求,也可能是web应用存在bug或某些临时故障
502 Bad Gateway 后端服务挂掉或者压力过大的时候, Nginx接到的请求无法及时传递给后端的服务进行处理,这个时候就会出现502错误。这个也非常常见,知乎豆瓣网站经常开小差的时候发生的错误就是这个。

参考https://juejin.cn/post/6844904202863394830

1.3 HTTP请求方法

1.3.1 GET

  1. GET 是最常用的方法。通常用于请求服务器发送某个资源

1.3.2 HEAD

类似于 GET 请求,只不过返回的响应中没有具体的内容,用于获取报头

1.3.3 POST

POST 方法起初是用来向服务器输入数据的。实际上,通常会用它来支持 HTML 的表单。表单中填好的数据通常会被送给服务器,然后由服务器将其发送到它要去的地方(比如,送到一个服务器网关程序中,然后由这个程序对其进行处理)。

1.3.4 PUT

从客户端向服务器传送的数据取代指定的文档的内容。与 GET 从服务器读取文档相反,PUT 方法会向服务器写入文档。有些发布系统允许用户创建 Web 页面,并用 PUT 直接将其安装到 Web 服务器上去。

1.4 网址,URL(Uniform Resource Locator ),域名

网址一般又称URL或域名,但域名和网址间还是有点区别的。 如https://www.baidu.com,域名指baidu.com,网址和url是https://www.baidu.com

1.5 网址组成

1.6 域名结构

域名结构层次:主机名.机构名.网络名.顶级域名

1.7 域名服务器

13个根域名https://www.internic.net/domain/named.root

1.8 域名解析过程

域名解析步骤: 1. 浏览器缓存 - 当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的IP地址(若曾经访问过该域名且没有清空缓存便存在); 2. 系统缓存 - 当浏览器缓存中无域名对应IP则会自动检查用户计算机系统Hosts文件DNS缓存是否有该域名对应IP; 3. 路由器缓存 - 当浏览器及系统缓存中均无域名对应IP则进入路由器缓存中检查,以上三步均为客服端的DNS缓存; 4. ISP(互联网服务提供商)DNS缓存 - 当在用户客服端查找不到域名对应IP地址,则将进入ISP DNS缓存中进行查询。比如你用的是电信的网络,则会进入电信的DNS缓存服务器中进行查找; 5. 根域名服务器 - 当以上均未完成,则进入根服务器进行查询。全球仅有13台根域名服务器,1个主根域名服务器,其余12为辅根域名服务器。根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器IP告诉本地DNS服务器; 6. 顶级域名服务器 - 顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的IP地址告诉本地DNS服务器; 7. 主域名服务器 - 主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,并重复该步骤直至找到正确纪录; 8. 保存结果至缓存 - 本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器建立链接。

1.9 DNS递归查询和迭代查询

  • 递归查询:主机向本地域名服务器的查询一般都是采用递归查询
  • 特点:本地DNS服务器只返回一次结果给客户端
  • 迭代查询:本地域名服务器向根域名服务器的查询的迭代查询。
  • 特点:本地DNS服务器多次与顶层DNS服务器通信

1.10 如何刷新dns缓存

windows上

ipconfig /flushdns

1.11 从浏览器输入网址发生了什么

参考https://juejin.cn/post/6844903922084085773 大致步骤如下: 1. URL 解析 2. DNS 查询 3. TCP 连接 4. 处理请求 5. 接受响应 6. 渲染页面

2 网络模型

2.1 OSI七层网络模型

  1. 物理层 (Physical Layer):物理层是 OSI 参考模型的最低层,它利用传输介质为数据链路层提供物理连接。它主要关心的是通过物理链路从一个节点向另一个节点传送比特流,物理链路可能是铜线、卫星、微波或其他的通讯媒介。它关心的问题有:多少伏电压代表 1 ?多少伏电压代表 0 ?时钟速率是多少?采用全双工还是半双工传输?总的来说物理层关心的是链路的机械、电气、功能和规程特性。
  2. 数据链路层 (Data Link Layer):数据链路层是为网络层提供服务的,解决两个相邻结点之间的通信问题,传送的协议数据单元称为数据帧。数据帧中包含物理地址(又称 MAC 地址)、控制码、数据及校验码等信息。该层的主要作用是通过校验、确认和反馈重发等手段,将不可靠的物理链路转换成对网络层来说无差错的数据链路。此外,数据链路层还要协调收发双方的数据传输速率,即进行流量控制,以防止接收方因来不及处理发送方来的高速数据而导致缓冲器溢出及线路阻塞。
  3. 网络层 (Network Layer):网络层是为传输层提供服务的,传送的协议数据单元称为数据包(分组)。该层的主要作用是解决如何使数据包通过各结点传送的问题,即通过路径选择算法(路由)将数据包送到目的地。另外,为避免通信子网中出现过多的数据包而造成网络阻塞,需要对流入的数据包数量进行控制(拥塞控制)。当数据包要跨越多个通信子网才能到达目的地时,还要解决网际互连的问题。
  4. 传输层 (Transport Layer):传输层的作用是为上层协议提供端到端的可靠和透明的数据传输服务,包括处理差错控制和流量控制等问题,传输层传送的协议数据单元称为数据段(报文)。该层向高层屏蔽了下层数据通信的细节,使高层用户看到的只是在两个传输实体间的一条主机到主机的、可由用户控制和设定的、可靠的数据通路。
  5. 会话层 (Session Layer):会话层主要功能是管理和协调不同主机上各种进程之间的通信(对话),即负责建立、管理和终止应用程序之间的会话。会话层得名的原因是它很类似于两个实体间的会话概念。例如,一个交互的用户会话以登录到计算机开始,以注销结束。
  6. 表示层 (Presentation Layer):数据压缩、加密以及数据描述,这使得应用程序不必关心在各台主机中数据内部格式不同的问题。
  7. 应用层 (Application Layer):应用层是 OSI 参考模型的最高层,是用户与网络的接口。该层通过应用程序来完成网络用户的应用需求,如文件传输、收发电子邮件等。

DNS属于应用层协议

2.2 TCP/IP模型

TCP/IP模式简化了OSI模型,只分四层

2.2.1 IP

IP 地址被分为 5 个类别 此外还有私有地址,不会在internet网上出现,用于企业网络(内网) - 1 个A类地址:10.0.0.0~10.255.255.255/8 ($2^{24}$ 个地址) - 16 个B类地址:172.16.0.0~172.31.255.255/16 ($162^{16}$ 个地址) - 256个C类地址:192.168.0.0~192.168.255.255/24 ($2562^8$ 个地址)

表一:IP地址的分配范围

网络类别 最大可分配网络数 第一个可分配网络号 最后一个可分配网络号 每一个网络中主机最大数
A $2^{7}-2$ 1 126 $2^{24}-2$
B $2^{14}-1$ 128.1 191.255 $2^{16}-2$
C $2^{21}-1$ 192.0.1 223.255.255 $2^{8}-2$

表二:特殊的IP地址

网络号 主机号 范围 源地址使用 目的地址使用 含义
0 0 0.0.0.0 可以 不可以 在本网络上的本主机
127 非全0或非全1 可以 可以 用于本地软件环回测试

IP数据包结构组成如下: IP数据包中记录了(部分) - 源IP地址(Source Addresses) - 目标IP地址(Destination Addresses) - 分段序号(Fragment Offset) - 生存时间(TTL) - 上层协议类型(Protocol):用于标识数据块交付给udp还是tcp或者icmp等。 - IP数据报长度(Total Length):$2^{16}-1=65535$,但要受MTU(Maximum Transmission Unit)限制,MTU一般1500字节

title: IP头部字节数
IP头部范围20~60字节。
IP头部字节数由IHL(占4bit)标识,计算公式=$IHL*4byte$,IHL占4bit,最大表示15,所以最大值是60.
title: TTL作用
TTL长度8 bit,最大值是255,TTL的一个推荐值是64。虽然从字面上翻译,TTL是IP数据包在计算机网络中的存在的最长时间。但实际上TTL是IP数据包在网络中可以转发的最大跳数。TTL字段由IP数据包的发送者设置,在IP数据包从源到目的的整个转发路径上,每经过一个路由器,把该TTL的值减1,然后再将IP包转发出去。如果在IP包到达目的IP之前,TTL减少为0,路由器将会丢弃收到的TTL=0的IP包并向发送者发送 ICMP time exceeded消息。TTL的主要作用是避免IP包在网络中的无限循环和收发,节省了网络带宽,并能使IP包的发送者能收到告警消息。这个字段可以防止由于故障而导致IP包在网络中不停被转发。
title: 分段序号作用
该字段对包含分段的上层数据包的IP包赋予序号。由于IP包在网络上传送的时候不一定能按顺序到达,这个字段保证了目标路由器在接受到IP包之后能够还原分段的上层数据包。到某个包含分段的上层数据包的IP包在传送是丢失,则整个一系列包含分段的上层数据包的IP包都会被要求重传。

2.2.2 TCP

TCP(Transmission Control Protocol)为应用程序之间提供面向连接的可靠的字节流服务。TCP为全双工协议,提供流控制机制,即允许接收方控制发送方的发送速度,此外还提供拥塞控制功能。 - TCP头部组成如下 - Source Port(Destination Port) - Sequence Number:用于对字节流进行编号,例如序号为 301,表示第一个字节的编号为 301,如果携带的数据长度为 100 字节,那么下一个报文段的序号应为 401。主要用来解决网络报乱序的问题; - Acknowledgment Number:期望收到的下一个报文段的序号。例如 B 正确收到 A 发送来的一个报文段,序号为 501,携带的数据长度为 200 字节,因此 B 期望下一个报文段的序号为 701,B 发送给 A 的确认报文段中确认号就为 701。 - Window Size:窗口大小,也就是有名的滑动窗口,用来进行流量控制。指定从被确认的字节算起可以发送多少个字节,窗口大小字段为0是合法的,说明已经接收到了 确认号-1 个字节,但是接收端没有来得及取走数据。 - ACK:此标志表示应答域有效,就是说前面所说的TCP应答号将会包含在TCP数据包中; - SYN:表示同步序号,用来建立连接。SYN标志位和ACK标志位搭配使用,当连接请求的时候,SYN=1,ACK=0;连接被响应的时候,SYN=1,ACK=1; - FIN:表示发送端已经达到数据末尾,也就是说双方的数据传送完成,没有数据可以传送了。

2.2.3 TCP3次握手4次挥手

titke: 为什么acknum=seq+1?
在建立连接时,tcp携带的数据是空的,这时标准默认+1。
在传输数据过程中,acknum=seq+datasize。
title: 为什么需要3次握手?
避免失效的连接请求到达服务端时,服务端再次确认连接请求,并又一次向客户端发送确认连接报文段。
title: 为什么要4次挥手
客户端发送FIN报文段给服务端时,服务端首先响应客户端的断开请求,但服务端可能还有数据需要传输给客户端;所以当服务端也发送完毕数据后又发送FIN报文段给客户端,表明我数据也发完了,可以关闭连接了。
title: 为什么需要TIME_WAIT
1. 确保最后一个确认报文能够到达。如果 B 没收到 A 发送来的确认报文,那么就会重新发送连接释放请求报文,A 等待一段时间就是为了处理这种情况的发生。

2. 等待一段时间是为了让本连接持续时间内所产生的所有报文都从网络中消失,使得下一个新的连接不会出现旧的连接请求报文。
title: 为什么TIME_WAIT是2MSL
其中MSL(Maximum Segment Lifetime)表示报文段的最大生命周期,在Linux上MSL是30秒。

1. 保证TCP协议的全双工连接能够可靠关闭(客户端和服务端均正常关闭连接)
2. 保证这次连接的重复数据段从网络中消失(因为极端情况下,一来一回需要的最大时间就是2MSL。)
title: syn攻击
攻击客户端在短时间内伪造大量不存在的IP地址,向服务器不断地发送SYN包,服务器回复确认包,并等待客户的确认。由于源地址是不存在的,服务器需要不断的重发直至超时,这些伪造的SYN包将长时间占用未连接队列,正常的SYN请求被丢弃,导致目标系统运行缓慢,严重者会引起网络堵塞甚至系统瘫痪。SYN 攻击是一种典型的 DoS/DDoS 攻击。

参考资料1:TCP的seq和ack号计算方法

2.2.4 TCP 滑动窗口

  • TCP头部window size块指定了接收端可以接收数据的大小;
  • 发送窗口内的字节都允许被发送,接收窗口内的字节都允许被接收。如果发送窗口左部的字节已经发送并且收到了确认,那么就将发送窗口向右滑动一定距离,直到左部第一个字节不是已发送并且已确认的状态;接收窗口的滑动类似,接收窗口左部字节已经发送确认并交付主机,就向右滑动接收窗口。

2.2.5 TCP 流量控制

流量控制是为了控制发送方发送速率,保证接收方来得及接收。

接收方发送的确认报文中的窗口字段可以用来控制发送方窗口大小,从而影响发送方的发送速率。将窗口字段设置为 0,则发送方不能发送数据。

2.2.6 TCP 拥塞控制

如果网络出现拥塞,分组将会丢失,此时发送方会继续重传,从而导致网络拥塞程度更高。因此当出现拥塞时,应当控制发送方的速率。这一点和流量控制很像,但是出发点不同。流量控制是为了让接收方能来得及接收,而拥塞控制是为了降低整个网络的拥塞程度。 TCP 主要通过四个算法来进行拥塞控制: 1. 慢开始 2. 拥塞避免 3. 快重传 4. 快恢复。

3 一些网络设计机制

3.1 心跳机制

  • 参考
  • 心跳作用:
  • 保持连接:一个客户端连接服务器以后,如果长期没有和服务器有数据来往,可能会被防火墙程序关闭连接,有时候我们并不想要被关闭连接。
  • 检测死链

3.1.1 TCP 的 keepalive 选项

  • 设置 keepalive
//on 是 1 表示打开 keepalive 选项,为 0 表示关闭,0 是默认值  
inton = 1;  
setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof(on));
  • 我们可以使用如下命令查看 Linux 系统上的上述三个值的设置情况:以下 linux 下是默认配置
$ sysctl -a | grep keepalive
net.ipv4.tcp_keepalive_time = 7200
net.ipv4.tcp_keepalive_probes = 9
net.ipv4.tcp_keepalive_intvl = 75

上面的 keepalive 选项表示如果一个连接上 7200s 后没有任何数据发送,则设置了这个选项的端向对端发送 keepalive 保活报文,它会有如下三种结果: - 对端回复ACK。则本端TCP认为该连接依然存活。继续等7200s后再发送keepalive报文。 - 对端回复RESET。说明对端进程已经重启,本端的应用程序应该关闭该连接。 - 没有对端的任何回复。则本端做重试,如果重试9次(前后重试间隔为75秒)仍然不可达,则向应用程序返回错误信息,ETIMEOUT(无任何应答)或EHOST - 设置 keepalive 选项

//发送 keepalive 报文的时间间隔  
intval = 7200;  
setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val));  
//两次重试报文的时间间隔  
intinterval = 75;  
setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &interval, sizeof(interval));  
intcnt = 9;  
setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &cnt, sizeof(cnt));