计算机网络总结
[计算机网络基础](https://javaguide.cn/cs-basics/network/other-network-questions.html#%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C%E5%9F%BA%E7%A1%80)
[网络分层模型](https://javaguide.cn/cs-basics/network/other-network-questions.html#%E7%BD%91%E7%BB%9C%E5%88%86%E5%B1%82%E6%A8%A1%E5%9E%8B)
[TCP/IP 四层模型是什么?每一层的作用是什么?](https://javaguide.cn/cs-basics/network/other-network-questions.html#tcp-ip-%E5%9B%9B%E5%B1%82%E6%A8%A1%E5%9E%8B%E6%98%AF%E4%BB%80%E4%B9%88-%E6%AF%8F%E4%B8%80%E5%B1%82%E7%9A%84%E4%BD%9C%E7%94%A8%E6%98%AF%E4%BB%80%E4%B9%88)
1. 应用层 2. 传输层 3. 网络层 4. 网络接口层 + 网络接口层的传输单位是帧(frame),IP 层的传输单位是包(packet),TCP 层的传输单位是段(segment),HTTP 的传输单位则是消息或报文(message)发送数据流程
[常见网络协议](https://javaguide.cn/cs-basics/network/other-network-questions.html#%E5%B8%B8%E8%A7%81%E7%BD%91%E7%BB%9C%E5%8D%8F%E8%AE%AE)
[应用层有哪些常见的协议?](https://javaguide.cn/cs-basics/network/other-network-questions.html#%E5%BA%94%E7%94%A8%E5%B1%82%E6%9C%89%E5%93%AA%E4%BA%9B%E5%B8%B8%E8%A7%81%E7%9A%84%E5%8D%8F%E8%AE%AE)
应用层常见协议
- HTTP(Hypertext Transfer Protocol,超文本传输协议):基于 TCP 协议,是一种用于传输超文本和多媒体内容的协议,主要是为 Web 浏览器与 Web 服务器之间的通信而设计的。当我们使用浏览器浏览网页的时候,我们网页就是通过 HTTP 请求进行加载的。
- SMTP(Simple Mail Transfer Protocol,简单邮件发送协议):基于 TCP 协议,是一种用于发送电子邮件的协议。注意 ⚠️:SMTP 协议只负责邮件的发送,而不是接收。要从邮件服务器接收邮件,需要使用 POP3 或 IMAP 协议。
- POP3/IMAP(邮件接收协议):基于 TCP 协议,两者都是负责邮件接收的协议。IMAP 协议是比 POP3 更新的协议,它在功能和性能上都更加强大。IMAP 支持邮件搜索、标记、分类、归档等高级功能,而且可以在多个设备之间同步邮件状态。几乎所有现代电子邮件客户端和服务器都支持 IMAP。
- FTP(File Transfer Protocol,文件传输协议) : 基于 TCP 协议,是一种用于在计算机之间传输文件的协议,可以屏蔽操作系统和文件存储方式。注意 ⚠️:FTP 是一种不安全的协议,因为它在传输过程中不会对数据进行加密。建议在传输敏感数据时使用更安全的协议,如 SFTP。
- Telnet(远程登陆协议):基于 TCP 协议,用于通过一个终端登陆到其他服务器。Telnet 协议的最大缺点之一是所有数据(包括用户名和密码)均以明文形式发送,这有潜在的安全风险。这就是为什么如今很少使用 Telnet,而是使用一种称为 SSH 的非常安全的网络传输协议的主要原因。
- SSH(Secure Shell Protocol,安全的网络传输协议):基于 TCP 协议,通过加密和认证机制实现安全的访问和文件传输等业务
- RTP(Real-time Transport Protocol,实时传输协议):通常基于 UDP 协议,但也支持 TCP 协议。它提供了端到端的实时传输数据的功能,但不包含资源预留存、不保证实时传输质量,这些功能由 WebRTC 实现。
- DNS(Domain Name System,域名管理系统): 基于 UDP 协议,用于解决域名和 IP 地址的映射问题。
关于这些协议的详细介绍请看 应用层常见协议总结(应用层) 这篇文章。
[传输层有哪些常见的协议?](https://javaguide.cn/cs-basics/network/other-network-questions.html#%E4%BC%A0%E8%BE%93%E5%B1%82%E6%9C%89%E5%93%AA%E4%BA%9B%E5%B8%B8%E8%A7%81%E7%9A%84%E5%8D%8F%E8%AE%AE)
传输层常见协议
- TCP(Transmission Control Protocol,传输控制协议 ):提供 面向连接 的,可靠 的数据传输服务。
- UDP(User Datagram Protocol,用户数据协议):提供 无连接 的,尽最大努力 的数据传输服务(不保证数据传输的可靠性),简单高效。
[网络层有哪些常见的协议?](https://javaguide.cn/cs-basics/network/other-network-questions.html#%E7%BD%91%E7%BB%9C%E5%B1%82%E6%9C%89%E5%93%AA%E4%BA%9B%E5%B8%B8%E8%A7%81%E7%9A%84%E5%8D%8F%E8%AE%AE)
网络层常见协议
- IP(Internet Protocol,网际协议):TCP/IP 协议中最重要的协议之一,属于网络层的协议,主要作用是定义数据包的格式、对数据包进行路由和寻址,以便它们可以跨网络传播并到达正确的目的地。目前 IP 协议主要分为两种,一种是过去的 IPv4,另一种是较新的 IPv6,目前这两种协议都在使用,但后者已经被提议来取代前者。
- ARP(Address Resolution Protocol,地址解析协议):ARP 协议解决的是网络层地址和链路层地址之间的转换问题。因为一个 IP 数据报在物理上传输的过程中,总是需要知道下一跳(物理上的下一个目的地)该去往何处,但 IP 地址属于逻辑地址,而 MAC 地址才是物理地址,ARP 协议解决了 IP 地址转 MAC 地址的一些问题。
- ICMP(Internet Control Message Protocol,互联网控制报文协议):一种用于传输网络状态和错误消息的协议,常用于网络诊断和故障排除。例如,Ping 工具就使用了 ICMP 协议来测试网络连通性。
- NAT(Network Address Translation,网络地址转换协议):NAT 协议的应用场景如同它的名称——网络地址转换,应用于内部网到外部网的地址转换过程中。具体地说,在一个小的子网(局域网,LAN)内,各主机使用的是同一个 LAN 下的 IP 地址,但在该 LAN 以外,在广域网(WAN)中,需要一个统一的 IP 地址来标识该 LAN 在整个 Internet 上的位置。
- OSPF(Open Shortest Path First,开放式最短路径优先) ):一种内部网关协议(Interior Gateway Protocol,IGP),也是广泛使用的一种动态路由协议,基于链路状态算法,考虑了链路的带宽、延迟等因素来选择最佳路径。
- RIP**(Routing Information Protocol,路由信息协议)**:一种内部网关协议(Interior Gateway Protocol,IGP),也是一种动态路由协议,基于距离向量算法,使用固定的跳数作为度量标准,选择跳数最少的路径作为最佳路径。
- BGP(Border Gateway Protocol,边界网关协议):一种用来在路由选择域之间交换网络层可达性信息(Network Layer Reachability Information,NLRI)的路由选择协议,具有高度的灵活性和可扩展性。
[HTTP](https://javaguide.cn/cs-basics/network/other-network-questions.html#http)
+ HTTP1.1默认连接为持久连接 + HTTP1.1大部分使用[从输入 URL 到页面展示到底发生了什么?(非常重要)](https://javaguide.cn/cs-basics/network/other-network-questions.html#%E4%BB%8E%E8%BE%93%E5%85%A5-url-%E5%88%B0%E9%A1%B5%E9%9D%A2%E5%B1%95%E7%A4%BA%E5%88%B0%E5%BA%95%E5%8F%91%E7%94%9F%E4%BA%86%E4%BB%80%E4%B9%88-%E9%9D%9E%E5%B8%B8%E9%87%8D%E8%A6%81)
> 类似的问题:打开一个网页,整个过程会使用哪些协议? >先来看一张图(来源于《图解 HTTP》):
上图有一个错误需要注意:是 OSPF 不是 OPSF。 OSPF(Open Shortest Path First,ospf)开放最短路径优先协议, 是由 Internet 工程任务组开发的路由选择协议
总体来说分为以下几个步骤:
- 在浏览器中输入指定网页的 URL。
- 浏览器通过 DNS 协议,获取域名对应的 IP 地址。
- 浏览器根据 IP 地址和端口号,向目标服务器发起一个 TCP 连接请求。
- 浏览器在 TCP 连接上,向服务器发送一个 HTTP 请求报文,请求获取网页的内容。
- 服务器收到 HTTP 请求报文后,处理请求,并返回 HTTP 响应报文给浏览器。
- 浏览器收到 HTTP 响应报文后,解析响应体中的 HTML 代码,渲染网页的结构和样式,同时根据 HTML 中的其他资源的 URL(如图片、CSS、JS 等),再次发起 HTTP 请求,获取这些资源的内容,直到网页完全加载显示。
- 浏览器在不需要和服务器通信时,可以主动关闭 TCP 连接,或者等待服务器的关闭请求。
[HTTP 状态码有哪些?](https://javaguide.cn/cs-basics/network/other-network-questions.html#http-%E7%8A%B6%E6%80%81%E7%A0%81%E6%9C%89%E5%93%AA%E4%BA%9B)
HTTP 状态码用于描述 HTTP 请求的结果,比如 2xx 就代表请求被成功处理。常见 HTTP 状态码
关于 HTTP 状态码更详细的总结,可以看我写的这篇文章:HTTP 常见状态码总结(应用层)。
请求头字段名 | 说明 | 示例 |
---|---|---|
Accept | 能够接受的回应内容类型(Content-Types)。 | Accept: text/plain |
Accept-Charset | 能够接受的字符集 | Accept-Charset: utf-8 |
Accept-Datetime | 能够接受的按照时间来表示的版本 | Accept-Datetime: Thu, 31 May 2007 20:35:00 GMT |
Accept-Encoding | 能够接受的编码方式列表。参考 HTTP 压缩。 | Accept-Encoding: gzip, deflate |
Accept-Language | 能够接受的回应内容的自然语言列表。 | Accept-Language: en-US |
Authorization | 用于超文本传输协议的认证的认证信息 | Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Cache-Control | 用来指定在这次的请求/响应链中的所有缓存机制 都必须 遵守的指令 | Cache-Control: no-cache |
Connection | 该浏览器想要优先使用的连接类型 | Connection: keep-alive Connection: Upgrade |
Content-Length | 以 八位字节数组 (8 位的字节)表示的请求体的长度 | Content-Length: 348 |
Content-MD5 | 请求体的内容的二进制 MD5 散列值,以 Base64 编码的结果 | Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ== |
Content-Type | 请求体的 多媒体类型 (用于 POST 和 PUT 请求中) | Content-Type: application/x-www-form-urlencoded |
Cookie | 之前由服务器通过 Set- Cookie (下文详述)发送的一个 超文本传输协议 Cookie | Cookie: $Version=1; Skin=new; |
Date | 发送该消息的日期和时间(按照 RFC 7231 中定义的"超文本传输协议日期"格式来发送) | Date: Tue, 15 Nov 1994 08:12:31 GMT |
Expect | 表明客户端要求服务器做出特定的行为 | Expect: 100-continue |
From | 发起此请求的用户的邮件地址 | From: user@example.com |
Host | 服务器的域名(用于虚拟主机 ),以及服务器所监听的传输控制协议端口号。如果所请求的端口是对应的服务的标准端口,则端口号可被省略。 | Host: en.wikipedia.org:80open in new window |
If-Match | 仅当客户端提供的实体与服务器上对应的实体相匹配时,才进行对应的操作。主要作用时,用作像 PUT 这样的方法中,仅当从用户上次更新某个资源以来,该资源未被修改的情况下,才更新该资源。 | If-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Modified-Since | 允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified ) | If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
If-None-Match | 允许在对应的内容未被修改的情况下返回 304 未修改( 304 Not Modified ) | If-None-Match: “737060cd8c284d8af7ad3082f209582d” |
If-Range | 如果该实体未被修改过,则向我发送我所缺少的那一个或多个部分;否则,发送整个新的实体 | If-Range: “737060cd8c284d8af7ad3082f209582d” |
If-Unmodified-Since | 仅当该实体自某个特定时间已来未被修改的情况下,才发送回应。 | If-Unmodified-Since: Sat, 29 Oct 1994 19:43:31 GMT |
Max-Forwards | 限制该消息可被代理及网关转发的次数。 | Max-Forwards: 10 |
Origin | 发起一个针对 跨来源资源共享 的请求。 | Origin: http://www.example-social-network.comopen in new window |
Pragma | 与具体的实现相关,这些字段可能在请求/回应链中的任何时候产生多种效果。 | Pragma: no-cache |
Proxy-Authorization | 用来向代理进行认证的认证信息。 | Proxy-Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ== |
Range | 仅请求某个实体的一部分。字节偏移以 0 开始。参见字节服务。 | Range: bytes=500-999 |
Referer | 表示浏览器所访问的前一个页面,正是那个页面上的某个链接将浏览器带到了当前所请求的这个页面。 | Referer: http://en.wikipedia.org/wiki/Main_Pageopen in new window |
TE | 浏览器预期接受的传输编码方式:可使用回应协议头 Transfer-Encoding 字段中的值; | TE: trailers, deflate |
Upgrade | 要求服务器升级到另一个协议。 | Upgrade: HTTP/2.0, SHTTP/1.3, IRC/6.9, RTA/x11 |
User-Agent | 浏览器的浏览器身份标识字符串 | User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:12.0) Gecko/20100101 Firefox/21.0 |
Via | 向服务器告知,这个请求是由哪些代理发出的。 | Via: 1.0 fred, 1.1 example.comopen in new window (Apache/1.1) |
Warning | 一个一般性的警告,告知,在实体内容体中可能存在错误。 | Warning: 199 Miscellaneous warning |
[HTTP 和 HTTPS 有什么区别?(重要)](https://javaguide.cn/cs-basics/network/other-network-questions.html#http-%E5%92%8C-https-%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB-%E9%87%8D%E8%A6%81)
HTTP 和 HTTPS 对比
- 端口号:HTTP 默认是 80,HTTPS 默认是 443。
- URL 前缀:HTTP 的 URL 前缀是
http://
,HTTPS 的 URL 前缀是https://
。 - 安全性和资源消耗:HTTP 协议运行在 TCP 之上,所有传输的内容都是明文,客户端和服务器端都无法验证对方的身份。HTTPS 是运行在 SSL/TLS 之上的 HTTP 协议,SSL/TLS 运行在 TCP 之上。所有传输的内容都经过加密,加密采用对称加密,但对称加密的密钥用服务器方的证书进行了非对称加密。所以说,HTTP 安全性没有 HTTPS 高,但是 HTTPS 比 HTTP 耗费更多服务器资源。
关于 HTTP 和 HTTPS 更详细的对比总结,可以看我写的这篇文章:HTTP vs HTTPS(应用层) 。
HTTP1.1/HTTP2.0/HTTP3的区别
> 如何查看请求使用的协议是HTTP1还是HTTP2? >- 打开开发者工具 ->选择“Network”标签页,在表头的竖线间隙处单击鼠标右键,勾选上“Protocol”选项。
[HTTP/1.1 和 HTTP/2.0 有什么区别?](https://javaguide.cn/cs-basics/network/other-network-questions.html#http-1-1-%E5%92%8C-http-2-0-%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB)
[3.6 HTTP/2 牛逼在哪?](https://www.xiaolincoding.com/network/2_http/http2.html#http-1-1-%E5%8D%8F%E8%AE%AE%E7%9A%84%E6%80%A7%E8%83%BD%E9%97%AE%E9%A2%98)(HTTP2详细)- HTTP2兼容HTTP1.1
- 多路复用(Multiplexing):HTTP/2.0 在同一连接上可以同时传输多个请求和响应,互不干扰。HTTP/1.1 则使用串行方式,每个请求和响应都需要独立的连接。
- 二进制帧:HTTP/2.0 使用二进制帧进行数据传输,而 HTTP/1.1 则使用文本格式的报文。二进制帧更加紧凑和高效,减少了传输的数据量和带宽消耗。
- 头部压缩:HTTP/1.1 支持Body压缩,Header不支持压缩。HTTP/2.0 支持对Header压缩。
- 服务器推送:HTTP/2.0 支持服务器推送,可以在客户端请求一个资源时,将其他相关资源一并推送给客户端,从而减少了客户端的请求次数和延迟。而 HTTP/1.1 需要客户端自己发送请求来获取相关资源。
[HTTP 是不保存状态的协议, 如何保存用户状态?](https://javaguide.cn/cs-basics/network/other-network-questions.html#http-%E6%98%AF%E4%B8%8D%E4%BF%9D%E5%AD%98%E7%8A%B6%E6%80%81%E7%9A%84%E5%8D%8F%E8%AE%AE-%E5%A6%82%E4%BD%95%E4%BF%9D%E5%AD%98%E7%94%A8%E6%88%B7%E7%8A%B6%E6%80%81)
HTTP 是一种不保存状态,即无状态(stateless)协议。也就是说 HTTP 协议自身不对请求和响应之间的通信状态进行保存。那么我们如何保存用户状态呢?Session 机制的存在就是为了解决这个问题,Session 的主要作用就是通过服务端记录用户的状态。典型的场景是购物车,当你要添加商品到购物车的时候,系统不知道是哪个用户操作的,因为 HTTP 协议是无状态的。服务端给特定的用户创建特定的 Session 之后就可以标识这个用户并且跟踪这个用户了(一般情况下,服务器会在一定时间内保存这个 Session,过了时间限制,就会销毁这个 Session)。在服务端保存 Session 的方法很多,最常用的就是内存和数据库(比如是使用内存数据库 redis 保存)。既然 Session 存放在服务器端,那么我们如何实现 Session 跟踪呢?大部分情况下,我们都是通过在 Cookie 中附加一个 Session ID 来方式来跟踪。
Cookie 被禁用怎么办?
最常用的就是利用 URL 重写把 Session ID 直接附加在 URL 路径的后面。
[URI 和 URL 的区别是什么?](https://javaguide.cn/cs-basics/network/other-network-questions.html#uri-%E5%92%8C-url-%E7%9A%84%E5%8C%BA%E5%88%AB%E6%98%AF%E4%BB%80%E4%B9%88)
+ URI(Uniform Resource Identifier) 是统一资源标志符,可以唯一标识一个资源。 + URL(Uniform Resource Locator) 是统一资源定位符,可以提供该资源的路径。它是一种具体的 URI,即 URL 可以用来标识一个资源,而且还指明了如何 locate 这个资源。URI 的作用像身份证号一样,URL 的作用更像家庭住址一样。URL 是一种具体的 URI,它不仅唯一标识资源,而且还提供了定位该资源的信息。
[Cookie 和 Session和Token 有什么区别?](https://javaguide.cn/cs-basics/network/other-network-questions.html#cookie-%E5%92%8C-session-%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB)
+ cookie - 储存在客户端本地;每次客户端发起 HTTP 请求时,浏览器会自动附上与该请求域名相关的所有 Cookie,作为请求头的一部分发送给服务器;由于 Cookie 存储在客户端,容易受到(XSS),可以设置 HttpOnly 标志防止 JavaScript 访问; + session:储存在服务器上;当用户首次访问服务器时,服务器为其创建一个唯一的会话 ID(Session ID),并将其以 Cookie 的形式发送给客户端。客户端后续请求时携带这个 Session ID,服务器通过识别它来关联到对应的会话数据,从而维持用户状态; + Token:储存在浏览器的 localStorage 或内存中;并在每个请求的 Authorization 头部以 Bearer 方式发送给服务器;一般用JWT来实现Token,一般用来储存用户的身份等信息,不储存密码等敏感信息。[GET 和 POST 的区别](https://javaguide.cn/cs-basics/network/other-network-questions.html#get-%E5%92%8C-post-%E7%9A%84%E5%8C%BA%E5%88%AB)
+ 使用场景不同:get用来获取查询结果,post用来修改和添加资源; + 幂等性:get是幂等的,多次重复执行不会改变资源的状态,post是不幂等的; + 请求参数格式:get请求通常放在url后面,url的长度会受服务器的限制,所以get请求的参数大小也是有限制的;post是请求体中; + 缓存:get是幂等的,其适合用来缓存,而post不行HTTP幂等
+ HTTP幂等性是指相同的请求在执行一次或多次的情况下,所产生的效果是相同的,不会对资源状态造成额外的变化。换句话说,无论对一个幂等的HTTP请求执行一次还是多次,最终结果都应该是一样的。 + 幂等:GET,HEAD,PUT,Delete是幂等的,post不是幂等的。HTTP缓存
+ HTTP 缓存有两种实现方式,分别是强制缓存和协商缓存 + 强缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。协商缓存是当本地的缓存过期后,和浏览器协商是否仍使用本地的缓存。 +  + HTTP缓存相关参数: + [前端 HTTP面试题:谈谈你对http缓存的理解?_哔哩哔哩_bilibili](https://www.bilibili.com/video/BV1H94y1u7MX/?spm_id_from=333.337.search-card.all.click&vd_source=add54d0fcd49c96c6c124259f9775bc3)HTTP和RPC
[3.8 既然有 HTTP 协议,为什么还要有 RPC?](https://www.xiaolincoding.com/network/2_http/http_rpc.html#%E4%BD%BF%E7%94%A8%E7%BA%AF%E8%A3%B8-tcp-%E4%BC%9A%E6%9C%89%E4%BB%80%E4%B9%88%E9%97%AE%E9%A2%98)- http是超文本协议,适用于大多数 Web 应用;rpc是远程调用并不是一种协议,而是一种调用方式;rpc的目的是屏蔽网络细节,调用远程服务端的方法可以像本地方法一样调用;rpc的实现有grcp;RPC 更适合微服务架构和需要高效通信的场景。http和大多数rpc基于tcp上定义的协议,但是rpc不一定非要基于tcp
- 服务发现:http知道服务器的域名就可以通过DNS找到ip;而一般会有专门的中间服务去保存服务名和IP信息,想要访问某个服务,就去这些中间服务去获得 IP 和端口信息;
- 性能:RPC 通常使用二进制序列化格式(如 Protocol Buffers、Thrift、Avro 等)来编码请求和响应数据,而不是像 HTTP API 常见的文本格式(如 JSON、XML),二进制序列化格式具有紧凑(跟json对比消除了多余的空格), 高效解析 ( 计算机处理二进制数据比处理文本更快 )的优点;rpc传输的数据比较http去除了一些冗余数据。
HTTPS
+ 也是用 TCP 作为底层协议,并额外使用 SSL/TLS 协议用作加密和安全认证加密的种类
+ 可逆加密 - 对称加密:加密和解密的密钥相同;AES - 非对称加密:分为公钥和私钥,公钥加密,可以告诉别人,私钥解密,不能告诉别人;ssl/tls,RSA + 不可逆加密: - hash,MD5,安全散列函数SSL/TLS原理
+ 通信双方只需要一次非对称加密,交换对称加密的密钥,在之后的信息通信中,使用绝对安全的密钥,对信息进行对称加密,即可保证传输消息的保密性。- 交换加密等必要信息
- 验证服务器的可信度,并拿到服务器传递的公钥
- 客户端传递随机数用于生成对称公钥
- 数据用对称公钥加密传输
TCP
[4.1 TCP 三次握手与四次挥手面试题](https://www.xiaolincoding.com/network/3_tcp/tcp_interview.html#%E4%B8%BA%E4%BB%80%E4%B9%88%E9%9C%80%E8%A6%81-tcp-%E5%8D%8F%E8%AE%AE-tcp-%E5%B7%A5%E4%BD%9C%E5%9C%A8%E5%93%AA%E4%B8%80%E5%B1%82)TCP粘包拆包问题
TCP在接受数据的时候,有一个滑动窗口来控制接受数据的大小,这个滑动窗口你就可以理解为一个缓冲区的大小。缓冲区满了就会把数据发送。数据包的大小是不固定的,有时候比缓冲区大有时候小。 如果一次请求发送的数据量比较小,没达到缓冲区大小,TCP则会将多个请求合并为同一个请求进行发送,这就形成了粘包问题; 如果一次请求发送的数据量比较大,超过了缓冲区大小,TCP就会将其拆分为多次发送,这就是拆包,也就是将一个大的包拆分为多个小包进行发送。1.TCP会发生粘包问题:TCP 是面向连接的传输协议,TCP 传输的数据是以流的形式,而流数据是没有明确的开始结尾边界,所以 TCP 也没办法判断哪一段流属于一个消息;TCP协议是流式协议;所谓流式协议,即协议的内容是像流水一样的字节流,内容与内容之间没有明确的分界标志,需要认为手动地去给这些协议划分边界。
粘包时:发送方每次写入数据 < 接收方套接字(Socket)缓冲区大小。
拆包时:发送方每次写入数据 > 接收方套接字(Socket)缓冲区大小。
2.UDP不会发生粘包问题:UDP具有保护消息边界,在每个UDP包中就有了消息头(UDP包长度、源端口、目的端口、校验和)。
粘包拆包问题在数据链路层、网络层以及传输层都有可能发生。日常的网络应用开发大都在传输层进行,由于UDP有消息保护边界,不会发生粘包拆包问题,因此粘包拆包问题只发生在TCP协议中
常见解决方法
1、客户端在发送数据包的时候,每个包都固定长度,比如1024个字节大小,如果客户端发送的数据长度不足1024个字节,则通过补充空格的方式补全到指定长度;
2、客户端在每个包的末尾使用固定的分隔符,例如\r\n,如果一个包被拆分了,则等待下一个包发送过来之后找到其中的\r\n,然后对其拆分后的头部部分与前一个包的剩余部分进行合并,这样就得到了一个完整的包;
3、将消息分为头部和消息体,在头部中保存有当前整个消息的长度,只有在读取到足够长度的消息之后才算是读到了一个完整的消息;
4、通过自定义协议进行粘包和拆包的处理。
HTTP解决TCP拆包粘包问题的方法
HTTP 协议定义,请求和响应都分为 http head 和 http body ,http head 和 body 通过 \r\n 区分,我们可以看到 在http 包头里 有 content-length 或Transfer-Encoding字段,``content-length` 用来确定 包体的长度因此就可以划分哪些数据应该是一个请求中的,达到区分的目的。- Transfer-Encoding: chunked:对于动态生成或长度未知的内容,可以使用分块传输编码(chunked encoding)。在这种模式下,主体被划分为一系列大小可变的数据块(chunks),每个数据块前面带有该块的长度(以十六进制表示),并以CRLF结尾。最后一个数据块长度为0,表示主体结束。这种方式允许在不知道主体总长度的情况下也能正确解析数据包边界。
为什么三次握手
+ 确保双方都知道自己和对方都能正常收发数据 + 避免历史连接,避免资源浪费 + 同步双方序列号,达到可靠传输TCP四次挥手
[4.1 TCP 三次握手与四次挥手面试题](https://www.xiaolincoding.com/network/3_tcp/tcp_interview.html#tcp-%E5%9F%BA%E6%9C%AC%E8%AE%A4%E8%AF%86)TCP重传,滑动窗口,流量控制,拥塞控制
[4.2 TCP 重传、滑动窗口、流量控制、拥塞控制](https://www.xiaolincoding.com/network/3_tcp/tcp_feature.html)- 重传机制
- 超时重传:数据包丢失,确认应答丢失都会超时重传;
- 超时重传的时间:当超时时间较大时,重发就慢,丢了老半天才重发,没有效率,性能差;当超时时间 较小时,会导致可能并没有丢就重发,于是重发的就快,会增加网络拥塞,导致更多的超时,更多的超时导致更多的重发;超时重传时间应该略大于报文往返时间;实际上报文往返时间是动态变化的,超时重传也是往返变化的;
- 超时重传:数据包丢失,确认应答丢失都会超时重传;
- 快速重传
- 不以时间为驱动,而是以数据驱动重传;
- SAK:可以将已收到的数据的信息发送给「发送方」,这样发送方就可以知道哪些数据收到了,哪些数据没收到,知道了这些信息,就可以只重传丢失的数据。
- DSAK
- 流量控制和拥塞控制都是对发送方进行控制的,流量控制是解决发送方和接收方不匹配产生的;拥塞控制是网络本身拥塞发送方采取的速率控制防止网络更加拥堵。
- 通过滑动窗口进行流量控制,
[WebSocket](https://javaguide.cn/cs-basics/network/other-network-questions.html#websocket)
[什么是 WebSocket?](https://javaguide.cn/cs-basics/network/other-network-questions.html#%E4%BB%80%E4%B9%88%E6%98%AF-websocket)
WebSocket 是一种基于 TCP 连接的全双工通信协议,即客户端和服务器可以同时发送和接收数据。WebSocket 协议在 2008 年诞生,2011 年成为国际标准,几乎所有主流较新版本的浏览器都支持该协议。不过,WebSocket 不只能在基于浏览器的应用程序中使用,很多编程语言、框架和服务器都提供了 WebSocket 支持。
WebSocket 协议本质上是应用层的协议,用于弥补 HTTP 协议在持久通信能力上的不足。客户端和服务器仅需一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输。
Websocket 示意图
下面是 WebSocket 的常见应用场景:
- 视频弹幕
- 实时消息推送,详见Web 实时消息推送详解open in new window这篇文章
- 实时游戏对战
- 多用户协同编辑
- 社交聊天
- ……
[WebSocket 和 HTTP 有什么区别?](https://javaguide.cn/cs-basics/network/other-network-questions.html#websocket-%E5%92%8C-http-%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB)
WebSocket 和 HTTP 两者都是基于 TCP 的应用层协议,都可以在网络中传输数据。下面是二者的主要区别:
- WebSocket 是一种双向实时通信协议,而 HTTP 是一种单向通信协议。并且,HTTP 协议下的通信只能由客户端发起,服务器无法主动通知客户端。
- WebSocket 使用 ws:// 或 wss://(使用 SSL/TLS 加密后的协议,类似于 HTTP 和 HTTPS 的关系) 作为协议前缀,HTTP 使用 http:// 或 https:// 作为协议前缀。
- WebSocket 可以支持扩展,用户可以扩展协议,实现部分自定义的子协议,如支持压缩、加密等。
- WebSocket 通信数据格式比较轻量,用于协议控制的数据包头部相对较小,网络开销小,而 HTTP 通信每次都要携带完整的头部,网络开销较大(HTTP/2.0 使用二进制帧进行数据传输,还支持头部压缩,减少了网络开销)。
[WebSocket 的工作过程是什么样的?](https://javaguide.cn/cs-basics/network/other-network-questions.html#websocket-%E7%9A%84%E5%B7%A5%E4%BD%9C%E8%BF%87%E7%A8%8B%E6%98%AF%E4%BB%80%E4%B9%88%E6%A0%B7%E7%9A%84)
WebSocket 的工作过程可以分为以下几个步骤:- 客户端向服务器发送一个 HTTP 请求,请求头中包含
Upgrade: websocket
和Sec-WebSocket-Key
等字段,表示要求升级协议为 WebSocket; - 服务器收到这个请求后,会进行升级协议的操作,如果支持 WebSocket,它将回复一个 HTTP 101 状态码,响应头中包含 ,
Connection: Upgrade
和Sec-WebSocket-Accept: xxx
等字段、表示成功升级到 WebSocket 协议。 - 客户端和服务器之间建立了一个 WebSocket 连接,可以进行双向的数据传输。数据以帧(frames)的形式进行传送,WebSocket 的每条消息可能会被切分成多个数据帧(最小单位)。发送端会将消息切割成多个帧发送给接收端,接收端接收消息帧,并将关联的帧重新组装成完整的消息。
- 客户端或服务器可以主动发送一个关闭帧,表示要断开连接。另一方收到后,也会回复一个关闭帧,然后双方关闭 TCP 连接。
另外,建立 WebSocket 连接之后,通过心跳机制来保持 WebSocket 连接的稳定性和活跃性。
[SSE 与 WebSocket 有什么区别?](https://javaguide.cn/cs-basics/network/other-network-questions.html#sse-%E4%B8%8E-websocket-%E6%9C%89%E4%BB%80%E4%B9%88%E5%8C%BA%E5%88%AB)
> 摘自[Web 实时消息推送详解open in new window](https://javaguide.cn/system-design/web-real-time-message-push.html)。 >SSE 与 WebSocket 作用相似,都可以建立服务端与浏览器之间的通信,实现服务端向客户端推送消息,但还是有些许不同:
- SSE 是基于 HTTP 协议的,它们不需要特殊的协议或服务器实现即可工作;WebSocket 需单独服务器来处理协议。
- SSE 单向通信,只能由服务端向客户端单向通信;WebSocket 全双工通信,即通信的双方可以同时发送和接受信息。
- SSE 实现简单开发成本低,无需引入其他组件;WebSocket 传输数据需做二次解析,开发门槛高一些。
- SSE 默认支持断线重连;WebSocket 则需要自己实现。
- SSE 只能传送文本消息,二进制数据需要经过编码后传送;WebSocket 默认支持传送二进制数据。
SSE 与 WebSocket 该如何选择?
SSE 好像一直不被大家所熟知,一部分原因是出现了 WebSocket,这个提供了更丰富的协议来执行双向、全双工通信。对于游戏、即时通信以及需要双向近乎实时更新的场景,拥有双向通道更具吸引力。
但是,在某些情况下,不需要从客户端发送数据。而你只需要一些服务器操作的更新。比如:站内信、未读消息数、状态更新、股票行情、监控数量等场景,SEE 不管是从实现的难易和成本上都更加有优势。此外,SSE 具有 WebSocket 在设计上缺乏的多种功能,例如:自动重新连接、事件 ID 和发送任意事件的能力。
[PING](https://javaguide.cn/cs-basics/network/other-network-questions.html#ping)
[PING 命令的作用是什么?](https://javaguide.cn/cs-basics/network/other-network-questions.html#ping-%E5%91%BD%E4%BB%A4%E7%9A%84%E4%BD%9C%E7%94%A8%E6%98%AF%E4%BB%80%E4%B9%88)
PING 命令是一种常用的网络诊断工具,经常用来测试网络中主机之间的连通性和网络延迟。这里简单举一个例子,我们来 PING 一下百度。
1 | # 发送4个PING请求数据包到 www.baidu.com |
PING 命令的输出结果通常包括以下几部分信息:
- ICMP Echo Request(请求报文)信息:序列号、TTL(Time to Live)值。
- 目标主机的域名或 IP 地址:输出结果的第一行。
- 往返时间(RTT,Round-Trip Time):从发送 ICMP Echo Request(请求报文)到接收到 ICMP Echo Reply(响应报文)的总时间,用来衡量网络连接的延迟。
- 统计结果(Statistics):包括发送的 ICMP 请求数据包数量、接收到的 ICMP 响应数据包数量、丢包率、往返时间(RTT)的最小、平均、最大和标准偏差值。
如果 PING 对应的目标主机无法得到正确的响应,则表明这两个主机之间的连通性存在问题(有些主机或网络管理员可能禁用了对 ICMP 请求的回复,这样也会导致无法得到正确的响应)。如果往返时间(RTT)过高,则表明网络延迟过高。
[PING 命令的工作原理是什么?](https://javaguide.cn/cs-basics/network/other-network-questions.html#ping-%E5%91%BD%E4%BB%A4%E7%9A%84%E5%B7%A5%E4%BD%9C%E5%8E%9F%E7%90%86%E6%98%AF%E4%BB%80%E4%B9%88)
PING 基于网络层的 **ICMP(Internet Control Message Protocol,互联网控制报文协议)**,其主要原理就是通过在网络上发送和接收 ICMP 报文实现的。ICMP 报文中包含了类型字段,用于标识 ICMP 报文类型。ICMP 报文的类型有很多种,但大致可以分为两类:
- 查询报文类型:向目标主机发送请求并期望得到响应。
- 差错报文类型:向源主机发送错误信息,用于报告网络中的错误情况。
PING 用到的 ICMP Echo Request(类型为 8 ) 和 ICMP Echo Reply(类型为 0) 属于查询报文类型 。
- PING 命令会向目标主机发送 ICMP Echo Request。
- 如果两个主机的连通性正常,目标主机会返回一个对应的 ICMP Echo Reply。
[DNS](https://javaguide.cn/cs-basics/network/other-network-questions.html#dns)
[DNS 的作用是什么?](https://javaguide.cn/cs-basics/network/other-network-questions.html#dns-%E7%9A%84%E4%BD%9C%E7%94%A8%E6%98%AF%E4%BB%80%E4%B9%88)
DNS(Domain Name System)域名管理系统,是当用户使用浏览器访问网址之后,使用的第一个重要协议。DNS 要解决的是**域名和 IP 地址的映射问题**。DNS:域名系统
在一台电脑上,可能存在浏览器 DNS 缓存,操作系统 DNS 缓存,路由器 DNS 缓存。如果以上缓存都查询不到,那么 DNS 就闪亮登场了。
目前 DNS 的设计采用的是分布式、层次数据库结构,DNS 是应用层协议,它可以在 UDP 或 TCP 协议之上运行,端口为 53 。
[DNS 服务器有哪些?根服务器有多少个?](https://javaguide.cn/cs-basics/network/other-network-questions.html#dns-%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%9C%89%E5%93%AA%E4%BA%9B-%E6%A0%B9%E6%9C%8D%E5%8A%A1%E5%99%A8%E6%9C%89%E5%A4%9A%E5%B0%91%E4%B8%AA)
DNS 服务器自底向上可以依次分为以下几个层级(所有 DNS 服务器都属于以下四个类别之一):- 根 DNS 服务器。根 DNS 服务器提供 TLD 服务器的 IP 地址。目前世界上只有 13 组根服务器,我国境内目前仍没有根服务器。
- 顶级域 DNS 服务器(TLD 服务器)。顶级域是指域名的后缀,如
com
、org
、net
和edu
等。国家也有自己的顶级域,如uk
、fr
和ca
。TLD 服务器提供了权威 DNS 服务器的 IP 地址。 - 权威 DNS 服务器。在因特网上具有公共可访问主机的每个组织机构必须提供公共可访问的 DNS 记录,这些记录将这些主机的名字映射为 IP 地址。
- 本地 DNS 服务器。每个 ISP(互联网服务提供商)都有一个自己的本地 DNS 服务器。当主机发出 DNS 请求时,该请求被发往本地 DNS 服务器,它起着代理的作用,并将该请求转发到 DNS 层次结构中。严格说来,不属于 DNS 层级结构
世界上并不是只有 13 台根服务器,这是很多人普遍的误解,网上很多文章也是这么写的。实际上,现在根服务器数量远远超过这个数量。最初确实是为 DNS 根服务器分配了 13 个 IP 地址,每个 IP 地址对应一个不同的根 DNS 服务器。然而,由于互联网的快速发展和增长,这个原始的架构变得不太适应当前的需求。为了提高 DNS 的可靠性、安全性和性能,目前这 13 个 IP 地址中的每一个都有多个服务器,截止到 2023 年底,所有根服务器之和达到了 600 多台,未来还会继续增加。