2025-12-22
网络编程
0

目录

计算机网络的体系结构
OSI 参考模型
TCP/IP 参考模型
五层原理参考模型
因特网的体系结构
DNS 域名系统
统一资源定位符
聊一聊 http 和 https
TCP 传输层协议
网络层
Web 服务进程
浏览器输入 www.taobao.com 回车之后发生了什么?

在海底捞二面的时候,面试官问了我一个大文件流传输的问题,用的 IO 会有哪些,我回答了 BIONIO 的内容,后来复盘了一下,觉得对网络编程方面的知识内容没有掌握彻底,还得再接再厉啊。

从一个最常见的场景入手,来看下你掌握网络编程的深度: “浏览器输入 www.taobao.com 回车之后发生了什么?”,你是否能回答上来这个问题呢?今天我将由浅入深的探索网络编程的原理,从 0-1 的告诉你网络交互的全流程,同时将涉及的基础内容都整理出来,做复习之用。

image.png

计算机网络的体系结构

计算机网络的体系结构是我们学习的重点,需要搭建自己的思维模型,掌握网络的结构模型。

OSI 参考模型

国际标准化的开放系统互联参考模型,也就是我们常说的 OSI 参考模型,它通过分层结构,将计算机网络分为七层,分别是:应用层 → 表示层 → 会话层 → 传输层 → 网络层 → 数据链路层 → 物理层,每一层都有特定的功能。

image.png

应用层:

应用层提供给用户网络服务,像文件传送、电子邮件、P2P应用等。

表示层:

表示层用于处理应用实体间交换数据的语法,其目的就是解决格式与数据表示的差别,从而为应用层提供一个统一的数据格式。

会话层:

会话层是指用户与用户的连接,通过在两台计算机之间建立、管理和终止通信来完成会话。

传输层:

传输层是端到端的层次,也是进程到进程的层次,数据的通信表面上看是在两台主机之间进行,实质上是发生在两个主机的进程之间。

为了防止传送途中报文的丢失,两个主机进程之间需要实现端到端控制。因为,传输层的功能主要包括 复用/分解(区分发送和接收主机上的进程)端到端的可靠数据传输、连接控制、流量控制和拥塞控制机制等。

网络层:

网络层解决的核心问题是如何分组通过交换网络传送至目的主机,因此,网络层的主要功能是数据转发与路由。网络层会对进入交换网络的通信量加以控制,比避免通信量过大造成交换网络性能下降。同时,网络层也具备寻址功能,确保分组可以被正确传输到目的主机,例如 Internet 网络中的 IP 地址。

数据链路层:

数据链路层的主要功能是实现在相邻节点之间数据可靠有效的传输。为了实现有效的差错控制,采用了一种以 “帧” 为单位的数据块传输方式。

物理层:

物理层的主要功能是在传输介质上实现无结构比特流传输。

TCP/IP 参考模型

因特网是全球覆盖范围最广、用户数量最多的互联网,采用了 TCP/IP 参考模型。这是一个四层协议的体系结构,依次是 应用层 → 传输层 → 网络层 → 网络接口层

image.png

TCP/IP 体系结构相当于将 OSI 体系结构的会话层和表示层合并到了应用层,将物理层和数据链路层合并到了网络接口层。

image.png

五层原理参考模型

TCP/IP 体系结构为了将不同的网络接口进行互联,其网络接口层并没有规定什么具体内容。然而,这对于我们学习计算机网络的完整体系而言,就会缺少一部分内容。因此,在学习计算机网络原理时往往采用折中的办法,也就是综合 OSI 参考模型喝 TCP/IP 参考模型的优点,采用一种五层原理参考模型,五层分别是:应用层 → 传输层 → 网络层 → 数据链路层 → 物理层

三种参考模型的整体对比效果图如下:

image.png

因特网的体系结构

实际应用的网络中几乎没有按照 OSI 参考模型创建的。OSI 参考模型是一种理论体系结构,是国际标准;而五层参考模型则是适合教学上的参考模型;TCP/IP 参考模型则是我们因特网体系结构真正应用的模型。

DNS 域名系统

用户在使用应用时,需要指定服务的IP地址和端口号,但是各种各样的 IP 地址让人望而生怯,所以就需要为服务主机起一个更容易读懂,有一定含义的名称,这就是域名的由来。

在使用网络应用时,在我们输入域名来指定访问的主机,单实际网络通信必须使用 IP 地址,如何将域名映射为协议使用的 IP 地址呢? 这就是域名系统(Domain Name System, DNS)的任务。

在应用通信前先需要请求 DNS 应用,将域名映射为 IP 地址,这个过程叫做域名解析。DNS域名解析分为以下两种方式:

  • 静态域名解析

静态域名解析是通过静态域名解析表进行的,即手动建立域名和IP地址之间的对应关系表,该表的作用可以将一些常用的域名放入表中。当DNS客户端需要域名所对应的IP地址时,即到静态域名解析表中去查找指定的域名,从而获得所对应的IP地址,提高域名解析的效率

  • 动态域名解析

动态域名解析需要专用的域名解析服务器(DNS服务器)运行域名解析服务器程序,提供从域名到IP地址的映射关系,负责接收客户提出的域名解析请求。

为提高查询速度,在解析域名时,首先采用静态域名解析的方法,如果静态解析不成功,再采用动态域名解析的方法。

DNS解析过程 - 本地缓存查询

当用户在浏览器中输入域名时,首先检查本地缓存(如hosts文件、DNS客户端缓存)是否有该域名的记录,如果有则直接返回IP地址,hosts文件是我们最常用的手段,工作中经常对域名的绑定IP进行重定向。

统一资源定位符

统一资源定位符(Uniform Resource Locator, URL)就是访问网络地址获取文档资源的。一般格式由四部分组成:

text
<协议>://<主机>:<端口>/<路径>

访问的 http://liushigong.cn 域名,实际全路径为 http://liushigong.cn:80/,默认 80 端口是不展示的,此处的路径为根路径 /,此处协议为应用层的协议。

应用层的协议如下:

image.png

聊一聊 http 和 https

接下来我们来了解一下开发中最常用 http/https 应用层协议,它们是基于传输层 TCP 协议进行统一封装通信数据的。

HTTP 也就是超文本传输协议,从名称上看就能分析出,其本质就是一个文本传输的格式,也称为协议。当浏览器进程访问 URL 时会发起与 WEB 服务的连接,当连接建立完成后,会通过连接向 Web 服务发送 Http 协议的报文,而这个过程也分为2种连接方式:

1)非持续连接方式

HTTP/1.0 采用非持续连接方式,在每次浏览器进程的请求都要与服务器建立一次 TCP 连接,当收到响应后就立即关闭连接,总结来看就是使用 短连接,每个请求需重新建立 TCP 连接,导致高延迟

2)持续连接方式

HTTP/1.1 支持持续连接方式,相比于非持续连接方式,浏览器进程在请求没有响应以前,可以连续发送多个 HTTP 请求报文,这样等服务器响应一个个请求的报文后再关闭。其引入 持久连接(默认开启 keep-alive),允许在同一个 TCP 连接上复用多个请求,并支持管道化(多个请求可同时发送,无需等待响应)。

队头阻塞

HTTP/1.1 虽然连接复用,提高了性能,但同样存在了一些缺陷,其中最主要的就是 队头阻塞(Head-Of-Line Blocking)

队头阻塞是指当顺序发送的请求序列中的一个请求因为某种原因被阻塞时,在后面排队的所有请求也一并被阻塞,会导致客户端迟迟收不到数据。

针对队头阻塞:

  1. 将同一页面的资源分散到不同域名下,提升连接上限。虽然能公用一个 TCP 管道,但是在一个管道中同一时刻只能处理一个请求,在当前的请求没有结束之前,其他的请求只能处于阻塞状态。

  2. 减少请求数量

  3. 内联一些资源:css、base64 图片等

  4. 合并小文件减少资源数

HTTP/2.0 采用二进制 分帧多路复用头部压缩 以显著提升性能。它们的关联点在于都基于请求/响应模型,并逐步演进以解决前版本的性能瓶颈。

队头阻塞问题的解决

HTTP/2.0 是基于 SPDY 协议,允许在一个连接上无限制并发流。多路复用,就是在一个 TCP 连接中可以存在多个流。一个域名对应一个连接,一个流代表了一个完整的请求-响应过程。帧是最小的数据单位,每个帧会标识出该帧属于哪个流,流也就是多个帧组成的数据流。

TCP 为了保证可靠传输,有一个“超时重传”机制,丢失的包必须等待重传确认。HTTP2 出现丢包时,整个 TCP 都要等待重传,那么就会阻塞该 TCP 连接中的所有请求。

总结对比

特性HTTP/1.0HTTP/1.1HTTP/2.0
连接类型短连接持久连接 + 管道多路复用(单一连接)
数据格式文本文本二进制分帧
头部传输重复完整发送重复完整发送压缩(HPACK)
服务器行为被动响应被动响应支持主动推送
队头阻塞存在(请求串行)部分解决(管道)彻底解决(流并行)

HTTPS(HyperText Transfer Protocol Secure)是一种通过 SSL/TLS 协议实现加密传输的超文本传输协议,用于保障网络通信安全。它并非独立协议,而是 HTTP 与 SSL/TLS 的结合体,通过加密通信内容、验证服务器身份和检测数据篡改,防范窃听、中间人攻击等安全威胁。

任何网站都应使用 HTTPS,尤其是那些需要登录凭据的网站。在现代 Web 浏览器(例如 Chrome)中,未使用 HTTPS 的网站与使用 HTTPS 的网站的标记有所不同。URL 栏中如出现挂锁,则表示该网页是安全的。Web 浏览器非常重视 HTTPS;Google Chrome 和其他浏览器将所有非 HTTPS 网站标记为不安全。

image.png

HTTPS 如何工作?

HTTPS 使用加密协议对通信进行加密。该协议称为传输层安全性 (TLS),但以前称为安全套接字层 (SSL)。该协议通过使用所谓的 非对称公钥基础架构 来保护通信。这种类型的安全系统使用两个不同的密钥来加密两方之间的通信:

  • 私钥 - 此密钥由网站所有者控制,并且如读者所推测的那样,它是私有的。此密钥位于 Web 服务器上,用于解密通过公钥加密的信息。
  • 公钥 - 所有想要以安全方式与服务器交互的人都可以使用此密钥。用公钥加密的信息只能用私钥解密。

image.png

TCP 传输层协议

TCP 是面向连接的传输层协议,应用程序在使用 TCP 之前,必须建立 TCP 连接。在数据传输完成后,必须释放已经建立的 TCP 连接。

TCP 提供双全工通信服务,即 TCP 允许通信双方的应用进程在任何时候都能发送数据和接收数据。TCP 为每块客户数据配上一个 TCP 首部,从而形成多个 TCP 报文段。这些报文段被交付给网络层,网络层将其分别封装在网络层 IP 数据报中,然后将这些 IP 数据报发送到网络中,最终到达目标主机。

image.png

TCP 连接管理中包括对连接的建立与拆除。TCP 连接建立主要通过的是 “三次握手” 的过程。

image.png

  • 第一次握手:客户端向服务端请求建立连接,SYN=1(建立连接),seq=x(序列号),客户端进入 SYN_SENT(同步已发送)状态。

  • 第二次握手:服务端向客户端返回确认并请求建立连接,SYN=1(建立连接),ACK=1 (已收到),ack=x+1(确认号为收到的序列号加一),seq=y(序列号),服务端进入 SYN_RCVD(同步已接收)状态。

  • 第三次握手:客户端向服务端发送确认报文,ACK=1 (已收到),ack=y+1(确认号为收到的序列号加一),seq=x+1(序列号),三次握手完成以后,2个主机之间,就可以传输数据啦~

为什么不采用二次握手建立连接?而一定采用三次握手建立连接呢?

TCP 采用三次握手建立连接,是为了确保双方连接彼此都清楚对方状态,从而保证可靠、稳定的建立连接,有效预防过期失效的连接请求达到后,导致无效链接的建立。

因为网络存在数据丢失,第二次握手控制段可能丢失,这样会导致主动发起连接的一方由于没有收到第二次握手控制段,则无法建立连接,而接受连接建立的一方则认为连接已建立,从而出现无效链接。另外,还是为了防止已失效的 TCP 连接请求报文段突然有传送到了 TCP 服务器进程。

当数据传输完成后,两台主机需要通过四次会话断开连接,这个过程我们称为 “四次挥手”。

image.png

  • 第一次挥手:客户端向服务端请求断开连接,FIN=1(断开连接),seq=u(序列号),客户端进入 FIN_WAIT_1(终止等待1)状态。

  • 第二次挥手:服务端向客户端返回确认报文,ACK=1 (已收到),ack=u+1(确认号为收到的序列号加一),seq=v(序列号),服务端进入 CLOSE_WAIT(关闭等待)状态,客户端进入 FIN_WAIT_2(终止等待1)状态。

  • 第三次挥手:服务端完成数据传输后,向客户端发送断开连接请求,FIN=1(断开连接),ACK=1 (已收到),ack=u+1(确认号为收到的序列号加一),seq=w(序列号),服务端进入 LAST_ACK(最后确认)状态。

  • 第四次挥手:客户端向服务端返回确认报文,ACK=1 (已收到),ack=w+1(确认号为收到的序列号加一),seq=u+1(序列号),客户端进入 TIME_WAIT(时间等待)状态,服务端进入 CLOSED(关闭)状态。

客户端处于 TIME_WAIT 状态时,TCP 连接还未释放掉,等待 2个 MSL(Maximum Segment Lifetime,最大段生命周期)的时长后,客户端进入 CLOSE 状态。

网络层

当 TCP 连接建立以后,开始进行数据传输,自上而下,就到了网络层,网络层的主要任务就是将分组从源主机经过多个网络和多段链路传输到目的主机,可以将此任务划分为 分组转发路由选择 两个功能,这里就不展开讲了,有兴趣的小伙伴可以自行学习。

在 TCP/IP 体系结构中,网络层的核心协议为 IP协议。在因特网当中,所有的异构网络的网络层都是使用了协议 IP,组成了IP网络,可以直接进行通信,无需关注寻址方案、路由选择协议等实现。

image.png

Web 服务进程

为了在不同的操作系统中区分不同的 PID 进程,采用端口号来标识和区分不同应用进程。端口号的长度为16比特,取值范围是 0 ~ 65535,分为两大类:

服务端使用的端口号

  • 全球通用端口号:取值范围是 0 ~ 1023

image.png

  • 登记端口号:取值范围是 1024 ~ 49151

这类端口号是为没有熟知端口号应用程序使用的。

客户端使用的短暂端口号

这类端口号仅在客户端使用,由客户进程在运行时动态选择,又称为临时端口号,取值范围是 49152 ~ 65535

注意

端口号是为了标识计算机中的各应用进程,只具有本地意义,在不同计算机中使用相同端口号没有任何关系,相互独立

我们使用最多的 WEB 服务莫过于 Nginx,在通过 IP 找到服务器主机,又通过端口号定位到我们的 Web 服务以后,通过反向代理,指向了我们的应用进程。

浏览器输入 www.taobao.com 回车之后发生了什么?

从整体来看,在输入域名后,会根据 url 查看浏览器是否缓存了该页面,通过 DNS 查询本地 hosts 缓存,路由器缓存,ISP缓存和根域名服务器去查询对应的IP。

浏览器将请求数据封装为 HTTP 请求报文,通过 TCP 三次握手建立连接,在传输层将报文封装为报文段,在经过网关和路由器后发送给 Web 服务,也就是通过端口号定位,到了我们的应用上面。

对于淘宝来说,请求会先到 nginx 服务器上,然后 nginx 采用默认的轮询算法进行负载均衡,将请求的报文发送给 Servlet 容器。

Servlet 容器接收到请求之后会解析请求行,请求体,请求头,然后交给 MVC 处理,像我们最常用的 Spring MVC,通过 DispatcherServlet 接收到请求后,通过请求路径返回相应的拦截器和 Controller,也就是我们的 MVC 的执行流程。

Controller 接口执行完成以后,会产生 Response 对象进行响应报文数据,浏览器接收 response 先攻数据后, 解析 HTTP 响应报文的头部包含了状态码(Status-Code),并进行缓存和解码,最后浏览器渲染页面

下一章分析应用网络IO的处理

上述流程中是从浏览器出发,找到 Web 服务的过程,那我们 Web 服务是如何与 TCP 建立的连接呢?对于我们开发者来说,如何提高网络并发性能才是根本,接下来我将深入应用中去探索这一过程。

本文作者:柳始恭

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!