网络原理(一)

网络原理(一)

大家好,今天咱们来把网络编程这块的核心知识,从底层Socket到上层HTTP协议,希望大家能获取新的知识!

一、网络编程入门:

网络编程的起点,永远绕不开Socket API,这是操作系统给我们提供的网络通信接口,不管是Java还是其他语言,底层都是封装了这套API。

1. Socket API基础:UDP与TCP的区别

首先咱们先分清UDP和TCP这两个最基础的传输层协议对应的API:

  • UDP :对应DatagramSocketDatagramPacket,它是无连接的、不可靠的传输,就像你寄信,只管把信丢进邮筒,不管对方收没收到,也不管顺序乱不乱。
  • TCP :对应ServerSocketSocket,它是面向连接的、可靠的传输,就像打电话,必须先拨通电话建立连接,才能开始说话,而且保证数据按顺序、无差错地送达。

这里有几个TCP Socket编程的基础注意点,是很多新手一开始就容易踩的坑:

  1. 读写数据的方式 :我们是通过Socket内置的InputStreamOutputStream来读写数据的,而读写的基本单位是字节。很多新手会在这里犯迷糊,比如直接读写字符串的时候,不考虑编码问题,或者忘记处理字节流的边界。
  2. 数据分隔符的约定 :客户端和服务器之间传递请求/响应时,必须约定好分隔符,最常见的就是换行符\n。比如你发一个请求,服务器读到\n就知道这个请求结束了,开始处理,否则就会一直等,或者把多个请求当成一个处理,导致解析错误。
  3. Socket的关闭 :服务器端通过accept()得到的Socket对象,在使用完之后一定要及时关闭,不然会造成文件描述符泄漏,服务器跑久了就会因为文件描述符耗尽而崩溃。
  4. 多客户端处理的困境 :要处理多个客户端连接,我们需要用到多线程或者线程池。每个客户端连接都创建一个新线程去处理,这样主线程才能继续accept新的连接。

2. 从多线程到IO多路复用:服务器模型的演进

上面说的多线程/线程池方案,在客户端数量不多的时候还能用,但如果客户端数量暴涨,就会出现一个问题:大量线程会带来巨大的系统开销。每个线程都需要占用内存,线程之间的切换也会消耗CPU资源,当客户端数量达到几万、几十万的时候,这种方式基本就不可行了。

那怎么解决这个问题?这里就引出了IO多路复用 ,这是当前开发服务器的主流核心技术,它的本质是:用一个线程同时负责处理多个客户端的请求

我给大家打个比方,一下就能明白:

  • 方案一:单线程处理:就像你一个人去买饭,要先买炒饭,买完再买油泼面,买完再买煎饼果子,一步一步来,效率极低,中间有任何一步卡住,后面的都得等。
  • 方案二:多线程处理:就像三个人一起去买,你买炒饭,师傅买油泼面,小汤买煎饼果子,效率提高了,但系统开销也大了,就像多线程会占用更多资源。
  • 方案三:IO多路复用:还是你一个人去买,但你不是等一个买完再买下一个,而是来回轮询:我先到炒饭摊前问"我的饭好了吗?",没好就去油泼面摊问"我的面好了吗?",再没好就去煎饼摊问,等哪个好了就先拿哪个。这样一来,你只需要用一个等待的时间,就同时等待了三个任务的完成。

对应到服务器上就是:

  • 多个客户端就像多个小摊的老板,每个客户端大部分时间都是空闲的,只是在等待数据,就像老板在给你做饭。
  • 服务器的线程就像你,不需要每个客户端都配一个线程,只需要用一个线程轮询,哪个客户端发来了数据,就去处理哪个,这样即使客户端很多,也能高效处理。

这里有几个关键点大家要注意:

  • 不是异步,是有点像:IO多路复用不是异步,它还是同步的,只是站在服务器的视角,把多个客户端的IO操作"复用"到一个线程里了。而异步IO是站在客户端的视角,上游等待下游的通知。
  • Java中的实现 :Java里通过NIO来封装了IO多路复用,这也是后续高并发服务器的基础。

二、应用层协议:从TCP/IP五层模型到自定义协议

聊完了传输层,咱们往上走,到应用层,这是程序员打交道最多的层次,我们写的代码只要涉及网络通信,都可以看作是应用层的一部分。

1. TCP/IP五层模型回顾

先快速过一下TCP/IP的五层模型,从下到上分别是:

  1. 物理层:处理硬件信号,比如网线、网卡这些底层的东西。
  2. 数据链路层:处理帧的传输,比如以太网协议。
  3. 网络层:处理IP地址和路由,核心协议是IP协议。
  4. 传输层:处理端到端的通信,就是我们刚才说的TCP和UDP。
  5. 应用层:处理具体的应用逻辑,比如HTTP、FTP这些协议,也是我们今天的重点。

这里要区分一下学校课程和实际工作的侧重点:

  • 学校的课程和面试考试,侧重的是应用层和传输层,网络层和数据链路层讲得比较浅。
  • 而实际工作中,尤其是Java后端开发,大部分精力都在网络通信上,用得最多的就是应用层的HTTP协议,Spring、Spring MVC这些框架,本质上都是围绕HTTP协议展开的。

2. 自定义应用层协议:核心思路与实践

应用层的很多协议,都是程序员自己定义的,比如我们要开发一个外卖APP的客户端和服务器,就需要约定一套双方都能看懂的协议,来传递请求和响应。自定义协议主要分两步:

第一步:明确传输的信息(需求分析)

首先要搞清楚,客户端和服务器之间要传递哪些数据。以外卖APP为例:

  • 客户端请求:用户的位置信息(经纬度)、用户的ID,服务器需要根据这些信息返回附近的商家列表。
  • 服务器响应:每个商家的ID、商家名称、商家图片、评分、配送费、分类(比如麻辣烫、水饺、快餐),可能会返回多条商家信息。

这些信息,就是我们协议里要约定的内容,必须先明确下来,才能设计后续的格式。

第二步:约定信息组织的格式

明确了要传什么,接下来就是怎么传,也就是数据的组织格式。常见的有以下几种方式:

方式一:行文本方式(最原始的方式)

这种方式非常简单,就是用换行符\n来分隔不同的信息,用空格或者其他符号来分隔同一行里的不同字段。

  • 请求示例用户id, 用户的位置\n,比如1000, 45E45N\n
  • 响应示例:每个商家占一行,字段之间用空格分隔,最后以空行结尾:
text 复制代码
1, 杨国福麻辣烫, 商家图片1.jpg, 4.8, 5, 麻辣烫\n
2, 大娘水饺, 商家图片2.jpg, 4.7, 0, 水饺\n
3, 麦当劳, 商家图片3.jpg, 5.0, 10, 快餐\n
\n

这种方式放到20年前非常常见,优点是简单、可读性强,缺点是不够灵活,而且如果数据里包含分隔符(比如商家名称里有逗号),就会出现解析错误。

方式二:XML格式

XML是一种标签式的结构化数据格式,和HTML很像,但XML的标签是可以自定义的,而HTML的标签是固定的。

  • 请求示例
xml 复制代码
<request>
    <userid>1000</userid>
    <position>75E75N</position>
</request>
  • 响应示例
xml 复制代码
<response>
    <shop>
        <id>1</id>
        <name>杨国福</name>
        <image>1.jpg</image>
        <rank>5.0</rank>
        <sendprice>5</sendprice>
    </shop>
</response>

XML的优点是可读性好、结构化清晰,缺点是冗余信息太多,会消耗更多的带宽,而对于服务器来说,带宽是非常宝贵的资源,硬盘最便宜,内存其次,CPU次之,带宽最费钱。所以现在除了一些老系统,很少用XML来做网络传输了,后续我们学习Maven的时候还会再见到它。

方式三:JSON格式(当前主流方式)

JSON是现在最流行的网络数据组织格式,它的可读性和XML差不多,但冗余信息比XML少很多,更节省带宽,是Java Web开发的基本盘,Spring、Spring Cloud这些框架都是基于JSON展开的。

  • 请求示例
json 复制代码
{
    "userid": 1000,
    "position": "75E75N"
}

JSON的优点是可读性好、节省带宽,缺点是还是存在一定的冗余信息,比如引号、冒号这些符号。

方式四:Protobuf(高性能场景专用)

Protobuf是基于二进制的格式,它会对数据进行压缩,完全不涉及JSON/XML里的冗余信息,带宽消耗最少,缺点是可读性非常差,人根本看不懂。

  • 它的工作方式是:约定一段二进制数据,哪几个字节表示哪个信息,比如前4个字节表示用户ID,接下来8个字节表示经纬度。
  • 这种方式主要用在性能要求非常高的场景,比如游戏服务器、高并发的后端服务,它是用开发效率换执行效率,C++开发里用得更多,Java里除非是高性能场景,否则一般用JSON就够了。

三、HTTP协议:Web开发的核心协议

聊完了自定义协议,接下来我们就来聊应用层最核心、面试和工作中都必考的协议------HTTP协议,这是当前Web开发中最核心的协议,我们平时用网站、写Spring代码,都是围绕HTTP协议展开的。

1. HTTP协议的背景与版本

HTTP协议诞生于1991年,是计算机圈子里的奇迹之年,这一年Java、Python、Linux、Qt、Vim、HTTP这些我们现在还在用的技术都诞生了。

  • HTTP/1.1:虽然是20年前的东西,但目前仍然是最流行的HTTP版本,我们后续的内容都以1.1版本展开介绍。
  • HTTP/2.0:2012-2014年推出,普及程度不高。
  • HTTP/3.0:最新的版本,有了新的机制,但新的东西总有坑,谁都不想当小白鼠,所以目前用得不多。

2. HTTP协议的核心模型:一问一答

HTTP协议是典型的一问一答模式:客户端发送一个请求,服务器就返回一个响应,请求和响应是一一对应的,就像你问朋友"吃了吗?",朋友回答"吃了",你再问"在干啥?",朋友再回答,这种一问一答的模式,非常适合浏览器打开网页、手机APP加载数据的场景。

网络通信中还有其他的模型,比如多问一答(上传大文件)、一问多答(下载大文件)、多问多答(远程控制),但HTTP这种一问一答的模式,是最通用、最容易实现的。

3. 抓包工具:学习HTTP协议的必备神器

要学习HTTP协议,光靠理论是不够的,我们需要一个重要的工具------抓包工具,它能帮我们获取网络数据包,把HTTP请求和响应的详细格式都解析出来,相当于我们学习网络的"显微镜"。

抓包工具的原理:代理

抓包工具的本质就是一个代理,我们先搞懂正向代理和反向代理的区别:

  • 正向代理:代表客户端干活,比如你买辣条,让小汤帮你去买,小汤就是你的正向代理,超市老板只知道钱和辣条,不知道是你买的。
  • 反向代理:代表服务器干活,比如你去买辣条,老板不在,他儿子帮他收钱、给辣条,你以为他儿子就是老板,这就是反向代理。

抓包工具就是一个正向代理,你电脑上所有的网络通信,都会先发给抓包程序,抓包程序再把数据转发给服务器,这样抓包工具就能拿到所有的HTTP数据了。

  • 这里要注意:梯子本质上也是代理,所以抓包工具和梯子可能会产生冲突,后续用抓包的时候,一定要关闭梯子或者梯子的浏览器插件。
  • 还有安全问题:抓包只能在你自己授权的情况下进行,不要在公共WiFi上随意抓包,也不要在公司的工作电脑上乱装不明来源的抓包工具,信息安全是当前互联网世界非常大的挑战。
常用抓包工具对比
  • Wireshark:知名的抓包工具,能抓很多协议,比如HTTP、TCP、UDP、IP、以太网数据帧,但使用起来门槛比较高,比较麻烦。
  • Fiddler:专门抓HTTP的工具,功能更简单,也足够我们学习用了,使用起来比Wireshark简单很多,推荐新手用这个。

Fiddler的版本选择:

  • Fiddler Everywhere:最新版,是收费的。
  • Fiddler Classic:经典版,免费的,我们用这个就够了。
  • 注意:国内下载网站要小心,很容易下到带广告的捆绑软件,尽量找正规渠道下载。
Fiddler的基础设置:支持HTTPS

我们现在大部分网站都是HTTPS的,所以要让Fiddler能抓到HTTPS的包,需要做简单的设置:

  1. 打开Fiddler的设置,找到HTTPS选项卡。
  2. 勾选Decrypt HTTPS traffic,然后会弹出一个对话框,提示你是否要信任Fiddler的根证书,这里一定要选yes,不然抓不到HTTPS的包,没选的话只能卸载重装了。

4. Fiddler界面与HTTP报文解析

打开Fiddler之后,我们就能看到电脑上所有的HTTP请求和响应了,界面上不同颜色代表不同的含义:

  • 红色:表示报错的请求。
  • 蓝色:表示请求得到了一个网页。
  • 绿色:表示请求得到了一个JS文件。
  • 灰色:表示响应的数据已经被缓存了。
HTTP请求报文解析

我们随便拿一个搜狗搜索的请求来看一下:

http 复制代码
GET https://www.sogou.com/web?query=Java HTTP/1.1
Host: www.sogou.com
Connection: keep-alive
Cache-Control: max-age=0
sec-ch-ua: "Chromium";v="130", "Google Chrome";v="130", "Not?A_Brand";v="99"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36
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.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: https://www.sogou.com/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cookie: cuid=AAG9L0bpRwAAAqHS2G9fgEASQU=; SUV=1697361968575328; ssuid=1145919238; SUID=DC8B8B7B741A910A00000000

这里我们可以看到HTTP请求的几个核心部分:

  1. 请求行GET https://www.sogou.com/web?query=Java HTTP/1.1,包含请求方法、请求URL、HTTP版本。
  2. 请求头 :比如HostUser-AgentAccept这些键值对,用来传递请求的附加信息,比如你是用什么浏览器发的请求,能接受什么类型的响应数据。
  3. 请求体:如果是POST请求,这里会有请求体,用来传递表单数据或者JSON数据,GET请求一般没有请求体。
HTTP响应报文解析

服务器返回的响应数据,大部分都是经过压缩的,比如用gzip压缩,这样可以节省网络带宽,提高传输效率,Fiddler会帮我们自动解压,我们可以看到响应的原始数据。


四、总结

  1. 基础Socket API:先搞懂TCP和UDP的区别,会写简单的客户端和服务器程序,理解字节流、分隔符、Socket关闭这些基础问题。
  2. IO模型演进:理解多线程的问题,再搞懂IO多路复用的原理,知道Java NIO的作用。
  3. 应用层协议设计:理解自定义协议的两个步骤,对比文本、XML、JSON、Protobuf的优缺点,知道什么场景用什么格式。
  4. HTTP协议与抓包:搞懂HTTP的一问一答模型,会用Fiddler抓包,能看懂HTTP请求和响应的报文结构。

这些内容,是Java后端开发的基础,不管是面试还是后续学习Spring、Spring MVC,都离不开这些知识。

相关推荐
952362 小时前
Spring IoC&DI
java·数据库·spring
十六年开源服务商2 小时前
游戏与设计驱动WordPress建站2026
java·前端·游戏
Johnstons2 小时前
网络诊断工具怎么选:从看到异常到真正定位根因的实战方法
网络·wireshark·抓包分析
前进吧-程序员2 小时前
C++ 内存到底分配在哪?
java·jvm·c++
NWU_白杨2 小时前
VoiceMockInterview项目MVP开发
java·ai
RDCJM2 小时前
Springboot的jak安装与配置教程
java·spring boot·后端
呱牛do it2 小时前
企业级门户网站设计与实现:基于SpringBoot + Vue3的全栈解决方案(Day 4)
java·vue
云烟成雨TD2 小时前
Spring AI Alibaba 1.x 系列【39】四大多智能体(Multi-agent)架构
java·人工智能·spring
Xingxing?!2 小时前
Java 后端分层架构详解
java·架构·状态模式