引言:
最近接触到了Java网络编程, 通过接下来几篇文章我将总结有关网络编程的基本知识和代码案例以便后续用来回顾,巩固知识
网络通信关键三要素
1. IP
1.1 核心定义
- IP地址(Internet Protocol Address)是分配给网络设备(如电脑、服务器、路由器、智能设备等)在TCP/IP网络(包括互联网)中进行唯一标识和逻辑定位的数字标签。它就像现实世界中的门牌号或电话号码,确保数据包能准确找到发送和接收的目的地。
1.2 核心目的和作用
- a. 唯一标识: 在特定网络范围内(如整个互联网或一个局域网内),一个IP地址通常只标识一个设备(或一个网络接口)。
- b. 逻辑寻址: 与物理地址(如MAC地址)不同,IP地址是基于网络拓扑分配的,具有层次性,方便路由器根据网络部分进行高效的路由选择和数据包转发。
- c. 端到端通信: 它是实现互联网上任意两台主机之间通信的基础。应用程序(如浏览器、邮件客户端)使用目标主机的IP地址来建立连接和发送数据。
1.3 IPv4
- a. 结构与表示
- 1. 长度: 32位(4字节)二进制数
- 2. 表示法: 点分十进制: 将32位分成4段(每段8位,称为一个八位组或字节),每段转换为十进制数(0-255),用点
.
分隔。这是最常用的形式。
- b. 地址组成 (网络部分+主机部分)
- 1. 关键概念: 一个IP地址不能孤立地看。它总是属于某个特定的网络。地址的一部分用于标识该设备所在的网络,另一部分用于标识该网络中的特定主机。
- 2. 类比: 电话号码 = 区号(网络部分) + 本地号码(主机部分)。
- 3. 区分: 需要借助子网掩码或CIDR前缀。
- c. 子网掩码
- 1. 作用: 明确指示IP地址中哪些位代表网络部分,哪些位代表主机部分。与IP地址成对出现
- 2. 长度与表示: 同样是一个32位二进制数,通常也写成点分十进制。
- 3. 规则:
网络部分在子网掩码中用连续的
1
表示。主机部分用连续的
0
表示。例如:
IP地址:
192.168.1.10
子网掩码:
255.255.255.0
(二进制:11111111 11111111 11111111 00000000
)解读:前24位(
192.168.1
)是网络地址,后8位(.10
)是主机地址。这个网络最多可以容纳254台主机(主机位全0是网络地址,全1是广播地址,不可用)。
4. CIDR表示法:
更简洁的方式。直接在IP地址后加
/
和一个数字(0-32),表示网络部分的位数。例如:
192.168.1.10/24
等同于 IP192.168.1.10
+ 子网掩码255.255.255.0
d. 特殊IP地址类型
网络地址: 主机部分全为
0
的地址。代表整个网络本身。192.168.1.0/24
广播地址: 主机部分全为
1
的地址。用于向该网络内的所有主机发送数据包。192.168.1.255/24
本地回环地址:
127.0.0.1
(通常是127.0.0.0/8
)用于测试本机的网络协议栈(如TCP/IP是否安装正确)。发送给这个地址的数据不会离开本机。私有IP地址: 为了解决IPv4地址枯竭问题,IANA保留了特定范围的地址供内部网络(如家庭、公司局域网)免费重复使用,这些地址不能直接在互联网上路由。需要通过网络地址转换才能访问公网。
公有IP地址: 除私有地址、特殊地址(如回环、组播)外的地址。由ICANN、RIRs、ISP分配和管理,是全球互联网上唯一的地址,可以直接在互联网上路由。你需要向ISP付费租用公网IP才能让你的服务器直接暴露在互联网上。
e. IP地址分配
静态IP: 手动为设备配置固定的IP地址、子网掩码、网关和DNS。适用于服务器、网络设备等需要固定地址的场景。配置复杂,管理麻烦。
动态IP: 通过DHCP协议自动获取IP地址、子网掩码、网关和DNS等信息。这是最常见的分配方式(家庭宽带、公司内网大部分客户端)。设备开机或接入网络时自动获取,租期结束后可能更换。
f. IP路由(寻址过程的核心)
1. 源主机: 检查目标IP地址是否在同一子网(用自己的子网掩码和目标IP进行“与”运算,再与自己的网络地址比较)。
2. 同一子网: 直接通过ARP获取目标主机的MAC地址,在数据链路层封装并发送。
3. 不同子网: 将数据包发送给默认网关(通常是本地网络出口的路由器)。源主机同样通过ARP获取网关的MAC地址。
4. 路由器: 收到数据包后:
检查目标IP地址。
查询自己的路由表(包含目标网络地址、子网掩码、下一跳地址/出接口等信息)。
根据最长前缀匹配原则,找到最精确的路由条目。
将数据包转发到相应的下一跳路由器或直接发送到目标网络。
5. 逐跳转发: 数据包经过多个路由器,每个路由器重复步骤4的过程,直到到达目标主机所在的网络。
6. 目标网络: 最后一跳路由器或目标主机所在网络的网关,将数据包发送给目标主机(通过ARP或已知的MAC地址)。
1.4 IPV6
- a. 驱动力: IPv4地址空间(约43亿)已耗尽,无法满足物联网等海量设备需求。
- b. 核心优势:
巨大的地址空间: 128位地址长度,提供约
3.4 x 10^38
个地址,几乎可以为地球上每粒沙子分配一个IP地址。简化报头: 固定长度的基本报头,提高路由器处理效率。
内置安全: IPSec支持成为标准(虽然实现上仍可选)。
无状态地址自动配置: 设备更容易自行配置地址。
更好的QoS支持: 流标签字段。
组播和任播增强: 更高效。
- c. 表示法: 8组4位十六进制数,用冒号
:
分隔。允许压缩连续的0(::
只能使用一次)。例如:
2001:0db8:85a3:0000:0000:8a2e:0370:7334
或压缩后2001:db8:85a3::8a2e:370:7334
- d. 特殊地址:
链路本地地址:
fe80::/10
(类似IPv4的APIPA,但设计更完善)。唯一本地地址:
fc00::/7
(类似IPv4的私有地址)。全球单播地址:
2000::/3
(类似IPv4的公网地址)。组播地址:
ff00::/8
。回环地址:
::1
。
- e. 无广播: IPv6取消了广播,完全用组播和任播代替。
- f. 与IPv4共存: 当前IPv4和IPv6网络共存(双栈、隧道、转换技术)。
- a. 结构与表示
2. 端口
2.1 核心定义
- 端口是一个16位(0-65535)的无符号整数,与IP地址配合使用,用于标识同一台主机上不同的网络应用程序或服务进程。它是实现多路复用(Multiplexing)的关键。
2.2 端口的意义
- a. IP地址的局限: IP地址只能定位到网络上的一台具体主机(设备)。但一台主机(比如你的电脑或服务器)上通常同时运行着多个网络应用程序(浏览器、微信、游戏客户端、Web服务器、数据库服务器等)。
- b. 通信隔离的需求: 当数据包到达目标主机时,操作系统需要知道具体应该交给哪个应用程序来处理这个数据包。不能让浏览器的网页数据跑到微信里去,也不能让发给数据库的查询请求被邮件客户端接收。
- c. 解决方案:端口! 想象一下:
IP地址 = 大楼地址 (定位到具体的建筑物)
端口号 = 房间号/门牌号 (定位到大楼里的具体住户/办公室)
数据包只有同时知道目标IP地址(哪栋楼) 和 端口号(哪个房间),才能准确送达目标应用程序。
2.3 核心作用与特性
- a. 多路复用/解复用:
发送端: 应用程序在发送数据时,会指定目标IP地址 + 目标端口号,以及自己的源IP地址 + 源端口号。
接收端: 操作系统内核的网络协议栈根据接收到的数据包中的目标端口号,将数据准确地分发(解复用) 给正在监听(Listen) 该端口的对应应用程序。
这样,一台主机就能同时运行多个网络服务,互不干扰。
- b. 传输层标识:
- 端口是 TCP/IP模型中传输层(Transport Layer) 的核心概念。TCP和UDP协议都使用端口号来区分不同的应用进程。
- c. 16位范围: 0 到 65535。
- d. 动态分配:
客户端端口: 通常由操作系统临时、随机分配(范围一般是 49152 - 65535,称为“动态端口”或“临时端口”)。当你的浏览器访问网站时,它使用的就是这类端口。用完(连接关闭)后会被回收复用。
服务端端口: 通常使用固定、知名的端口号(范围一般是 0 - 1023,称为“知名端口”或“系统端口”),以便客户端能够预先知道如何连接。例如:HTTP=80, HTTPS=443, SSH=22, FTP=21。1024 - 49151 称为“注册端口”,可供用户程序或不太通用的服务注册使用(如数据库常用端口)。
- a. 多路复用/解复用:
2.4 关键规则与分类
- a. 端口号范围:
0 - 1023: 知名端口 (Well-Known Ports): 由IANA分配和管理,用于系统级或广泛使用的关键服务。普通用户程序通常无法绑定这些端口(需要管理员权限)。
1024 - 49151: 注册端口 (Registered Ports): 可由公司或组织向IANA注册,用于特定的应用程序服务(如MySQL=3306, PostgreSQL=5432, Redis=6379)。用户程序可以绑定使用这些端口。
49152 - 65535: 动态/私有端口 (Dynamic/Ephemeral Ports): 由操作系统动态分配给客户端程序用于临时通信。服务器程序几乎不会监听这些端口(除非是P2P应用等特殊情况)。
- b. 绑定与监听:
- 服务端程序在启动时,会主动绑定 (bind) 到一个特定端口(通常是知名或注册端口),并监听 (listen) 该端口,等待客户端的连接请求。
一个端口在同一时刻、同一传输层协议(TCP或UDP) 上,只能被一个进程监听。试图绑定已被监听的端口会导致
bind
错误(通常是EADDRINUSE
)。
- c. 协议独立性 (TCP vs UDP):
- 同一个端口号可以同时用于TCP和UDP协议上的不同服务! 例如,端口53通常用于:
TCP: DNS Zone Transfers (区域传输)
UDP: DNS Queries (常规查询)
操作系统根据数据包是TCP还是UDP以及目标端口号来区分交给哪个进程。
- 同一个端口号可以同时用于TCP和UDP协议上的不同服务! 例如,端口53通常用于:
- a. 端口号范围:
3. 协议
3.1 TCP (Transmission Control Protocol)
3.1.1 核心特性与机制(理解这些就抓住了TCP的灵魂)
- a. 核心: 通信双方在正式传输数据前,必须先建立一条逻辑连接通道。传输结束后,必须释放连接。
- b. 三次握手建立连接:
1. SYN: 客户端发送一个SYN(同步)包(包含初始序列号ISN_C)给服务器,请求建立连接。
2. SYN-ACK: 服务器收到SYN包,同意建立连接,发送一个SYN-ACK包(包含自己的初始序列号ISN_S和对ISN_C+1的确认)。
3. ACK: 客户端收到SYN-ACK包,发送一个ACK包(包含对ISN_S+1的确认)。
目的: 双方交换初始序列号,确认对方具备收发能力,为可靠传输打下基础。
c. 四次挥手释放连接:
1. FIN: 主动关闭方(如客户端完成发送)发送FIN包,表示不再发送数据。
2. ACK: 被动关闭方(服务器)收到FIN,发送ACK确认。
3. FIN: 被动关闭方处理完剩余数据后,也发送FIN包。
4. ACK: 主动关闭方收到FIN,发送ACK确认。经过TIME_WAIT状态(通常2MSL,约1-4分钟)后彻底关闭。
目的: 确保双方都完成了数据的发送和接收,可靠地终止连接。
TIME_WAIT
确保网络中滞留的旧数据包消失,防止新连接的混淆。
d. 高可靠性 (Reliability): TCP的核心价值!
确认应答 (Acknowledgements - ACK): 接收方收到数据后,会发送一个ACK包给发送方,告知它某个序列号之前的数据都已成功接收。
超时重传 (Retransmission on Timeout): 发送方发出数据包后会启动一个定时器。如果在合理时间内未收到对应的ACK,则认为数据包丢失,会重新发送该数据包。
序列号 (Sequence Numbers): TCP为每个传输的字节分配一个唯一的序列号。接收方根据序列号:
按序重组: 确保数据按发送顺序交付给应用层(即使网络传输顺序被打乱)。
检测丢失和重复: 发现序列号不连续或重复,即可判断发生了丢包或重复。
e. 流量控制 (Flow Control):
滑动窗口 (Sliding Window): 接收方在ACK包中通告自己的接收窗口大小。这个窗口表示接收方当前缓冲区还能容纳多少字节的数据。
发送窗口限制: 发送方发送的数据量不能超过接收方通告的窗口大小。接收方处理完数据,腾出缓冲区空间后,会通告新的窗口大小,允许发送方继续发送更多数据。这是一个动态调节的过程。
f. 拥塞控制 (Congestion Control):
核心思想: 发送方通过感知网络拥塞程度(主要是丢包事件),主动降低自己的发送速率。
主要算法(简化理解):
慢启动 (Slow Start): 连接开始时或从拥塞中恢复时,发送窗口从一个很小的值开始,然后指数级增长(每收到一个ACK,窗口翻倍),快速探测可用带宽。
拥塞避免 (Congestion Avoidance): 当窗口增长到一个阈值(慢启动阈值)时,转为线性增长(每收到一个ACK,窗口增加1)。避免增长过快导致拥塞。
拥塞发生处理:
超时重传 (Timeout): 视为严重拥塞。将慢启动阈值设为当前拥塞窗口的一半,拥塞窗口重置为1,重新进入慢启动。
快速重传 (Fast Retransmit) / 快速恢复 (Fast Recovery): 收到3个重复ACK(表明可能只丢了一个包,网络拥塞不严重)。立即重传丢失包,将慢启动阈值设为当前拥塞窗口的一半,拥塞窗口设为新阈值(或略大),进入拥塞避免阶段。避免窗口降到1,效率更高。
目的: 防止发送方发送过快导致整个网络拥塞(路由器/链路过载)
g. 面向字节流 (Byte Stream):
核心: TCP把应用层交下来的数据看作一连串无结构的字节流,它不维护应用层消息的边界。
常见问题:
粘包问题: 发送方连续发送的多个小块应用数据(如两条消息),可能被TCP组合成一个大的TCP段发送出去,接收方一次
receive()
可能读到多条消息拼接在一起的数据。拆包问题: 发送方发送的一个大的应用数据块(如一个大文件),可能被TCP拆分成多个较小的TCP段发送,接收方可能需要多次
receive()
才能读取完整数据。
解决方案:
固定长度消息: 每条消息长度固定(不灵活)
特殊分隔符: 每条消息末尾添加特定分隔符(如
\n
,需转义)包含长度字段: 在消息头部添加一个固定长度的字段,指明后面数据的长度(最常用,如HTTP头部的
Content-Length
)
3.1.2 TCP的优缺点总结
- 优点:
可靠传输: 数据不丢、不错、不乱序。这是最核心的价值!
流量控制: 防止发送过快淹没接收方。
拥塞控制: 防止网络拥塞,公平共享带宽。
保证顺序: 数据按发送顺序交付。
缺点:
开销大: 头部大(20字节+选项),连接管理、确认、重传、控制机制都带来额外开销。
延迟高: 连接建立/断开需要时间,确认和重传机制、拥塞控制都会增加延迟。
速度相对慢: 相比UDP,吞吐量可能较低(尤其在拥塞网络或需要低延迟的场景)。
编程相对复杂: 需要处理连接管理、粘包拆包。
无法广播/组播: 仅支持一对一通信。
- 优点:
3.1.3 典型应用场景
对数据完整性、准确性、顺序性要求极高的应用:
文件传输 (FTP, SFTP)
网页浏览 (HTTP/HTTPS)
电子邮件 (SMTP, POP3, IMAP)
数据库连接
远程登录 (SSH, Telnet)
金融交易系统
3.2 UDP (User Datagram Protocol)
3.2.1 核心特性与机制(理解这些就抓住了UDP的灵魂)
- a. 无连接 (Connectionless):
- 核心: 通信前不需要建立逻辑连接。发送方想发就发,直接指定目标IP和端口。
没有握手: 没有TCP的三次握手过程。第一个数据包就是有效载荷。
没有状态: 通信双方不维护连接状态信息(如序列号、窗口大小)。服务器通常也不知道有哪些客户端会发送数据过来。
开销极低: 省去了建立和断开连接的开销,通信延迟最小。
b. 尽最大努力交付 (Best-Effort Delivery):
核心: UDP只提供最基本的传输功能,不保证:
数据到达: 数据包可能在网络中丢失,且发送方不会知道(除非应用层自己实现确认)。
数据顺序: 后发送的数据包可能先到达接收方。
数据不重复: 由于网络路径或重传机制(如果应用层做了),接收方可能收到重复的数据包。
数据完整性: 虽然有校验和,但如果校验失败,UDP会静默丢弃该数据包,不会通知发送方重传。
c. 面向数据报 (Datagram-Oriented):
核心: UDP维护应用层消息的边界。
发送端: 每次调用
send()
发送的数据,UDP会将其作为一个独立的、完整的数据报封装并发送。接收端: 每次调用
receive
()
接收的数据,会返回一个完整的发送端发出的数据报。如果接收缓冲区小于数据报大小,多余部分会被丢弃,并且这个不完整的包也不会传递给应用层。关键优势: 天然避免了TCP的粘包问题。每个
receive
()
调用读取到的都是发送方一次send()
发出的完整消息(前提是数据报没被分片且没在IP层被丢弃)。
d. 支持广播和组播 (Broadcast & Multicast):
核心: UDP数据包可以发送到特定的IP地址,实现:
广播: 发送到整个本地网络(如
255.255.255.255
或特定子网的广播地址,如192.168.1.255
)。所有主机都会收到。组播: 发送到特定的D类组播地址(
224.0.0.0
-239.255.255.255
)。只有加入了该组播组的主机才会处理这个数据包。应用场景: 实时音视频分发、网络发现、路由协议更新等需要一对多通信的场景。TCP无法做到这一点。
- a. 无连接 (Connectionless):
3.2.2 UDP的优缺点总结
优点:
低延迟: 无连接建立/断开开销,无确认重传等待。
低开销: 头部小,协议栈处理简单。
无连接状态: 服务器资源消耗少(内存、CPU),能支撑更多“连接”。
保留消息边界: 天然适合消息型应用。
支持广播/组播: 实现高效的一对多通信。
缺点:
不可靠: 数据可能丢失、乱序、重复。应用需自行处理(如需可靠性)。
无拥塞控制: 持续高速发送可能加剧网络拥塞,影响自己和他人。
无流量控制: 发送方可能淹没接收方,导致接收缓冲区溢出丢包。
数据报大小限制: 单次发送数据量有限制(需注意分片问题)。
3.2.3 典型应用场景
对实时性要求高,可容忍少量数据丢失的应用:
实时音视频通话/直播: 丢失几帧画面或音频比延迟卡顿体验更好 (VoIP, WebRTC, 直播流)。
在线游戏: 实时位置、状态更新(少量丢包可通过预测弥补)。
DNS查询: 请求响应快,且请求本身很小,重试成本低。
DHCP: 网络配置协议,基于广播/发现。
SNMP: 网络管理协议,周期性发送状态信息。
路由协议更新: (RIP, OSPF) 使用组播定期广播路由信息。
广播发现: 如寻找局域网内的打印机或服务 (
SSDP
)。QUIC协议基础: HTTP/3的底层传输协议,在UDP上实现了自己的可靠传输和拥塞控制。