ip网络通信类型补充:
在ipv4地址下:
● 单播(Unicast)平时上网与服务器之间1v1双向单播
● 广播(Broadcast) 网络广播一般是255.255.255.255或某个子网主机位全为1的网段,广播必须接收
● 组播(Multicast) D类地址可用于组播,组播是接收方自动加入
在ipv6地址下:
没有广播了,只有任播(anycast)
子网掩码补充
如何通过子网掩码划分,将192.168.1.0/24的网络,划分成2个子网?划分成4个呢?
先尝试将子网掩码往后移动一位
1100 0000.1010 1000.0000 0001.0|000 0000
1111 1111.1111 1111.1111 1111.1|000 0000 (子网掩码是255.255.255.128)
# 掩码后移之后,得到新的两个网络,主机位全0代表网络号
1100 0000.1010 1000.0000 0001.0|000 0000 (192.168.1.0/25)
1100 0000.1010 1000.0000 0001.1|000 0000 (192.168.1.128/25)
#1100 0000.1010 1000.0000 0001.10|00 0000(192.168.1.128/26)
#1100 0000.1010 1000.0000 0001.11|00 0000(192.168.1.192/26)
#1111 1111.1111 1111.1111 1111.11|00 0000
# 广播地址为主机位全为1,因此两个网络各自的广播地址为
1100 0000.1010 1000.0000 0001.0|111 1111 (192.168.1.127)
1100 0000.1010 1000.0000 0001.1|111 1111 (192.168.1.255)
# 各自子网可容纳的主机数
1100 0000.1010 1000.0000 0001.0|000 0001 - 1100 0000.1010 1000.0000 0001.0|111 1110 (192.168.1.1 - 192.168.1.126)
1100 0000.1010 1000.0000 0001.1|000 0001 - 1100 0000.1010 1000.0000 0001.1|111 1110 (192.168.1.129 - 192.168.1.254)
得到如下表格中的信息
| 子网 | 网络地址 | 范围 | 广播地址 |
|---|---|---|---|
| 第1个 /25 | 192.168.1.0/25 | 0 ~ 127 | 192.168.1.127 |
| 第2个 /25 | 192.168.1.128/25 | 128 ~ 255 | 192.168.1.255 |
这样划分之后,那这两个子网内部设备不需要经过路由转发,因为在同一个局域网直接通过arp协议广播就可以找到对方;
如果192.168.1.0/25内部的某个机器,需要与192.168.1.128/25内部的某个机器通信,就需要发给路由器了;
那主机如何判断目标地址是否与自己在一个局域网内部呢?非常简单:目标ip&子网掩码=自己的网段 满足等式就在一个局域网,否则不在。
ARP协议补充
| 路由器arp协议寻找目标设备 | 目标设备arp回答 | ipconfig /all 查看 |
|---|---|---|
![]() | ![]() | ![]() |



==总结==:




DHCP补充
自己尝试一下dhcp获取ip地址,并抓取dhcp报文
# 安装tcpdump,linux抓包工具
yum install tcpdump
# -i any 指定监听的网卡
# -n 不解析主机名,默认情况下 tcpdump 会尝试把 IP 地址反向解析成域名
# port 67 or port 68 过滤条件
# 67 DHCP 服务端监听端口
# 68 DHCP 客户端监听端口
# -w dhcp_capture.pcap 可以使用wireshark打开
tcpdump -i any -n port 67 or port 68 -w dhcp_capture.pcap
# 新开一个shell
# 删除保持通过dhcp获取的缓存ip信息
cd /var/lib/NetworkManager/
rm internal-7e7958c9-d951-3deb-af85-4459aa3dbe39-ens160.lease # 这个文件里面存放了dhcp获取的ip地址
nmcli connection down ens160 && sudo nmcli connection up ens160


自己设置ip地址


抓包文件示例:dhcp_capture.pcap
由抓包报文可以看出,dhcp基于udp协议,并且是应用层协议
网关(路由器)(==gateway==)




DNS域名解析补充
1. linux中/etc/hosts也保存了主机的域名映射关系
[root@192 ~]# cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
# 可以尝试将www.baidu.com 解析到127.0.0.1上
# 此文件保存了dns服务器地址,默认是网关地址
[root@192 ~]# cat /etc/resolv.conf
# Generated by NetworkManager
search localdomain
nameserver 192.168.18.2
# 可以尝试去掉,或者改成114.114.114.114,之后ping www.baidu.com将无法联通
2. dns解析相关的命令
ping www.baidu.com #可以触发dns解析
# 需要安装bind的工具包
yum install bind-utils
dig www.baidu.com #可以查看详细解析记录
nslookup www.baidu.com # 也可以查看详细解析记录
3. 域名购买和配置
● 可以去阿里云购买
● 域名解析怎么配置
![]() | ![]() |
|---|---|


配置网络参数补充
改ip参数和dns参数
vim /etc/NetworkManager/system-connections/ens160.nmconnection
[connection]
id=ens160
uuid=7e7958c9-d951-3deb-af85-4459aa3dbe39
type=ethernet
autoconnect-priority=-999
interface-name=ens160
timestamp=1781681830
[ethernet] ← 保持不变
[ipv4]
method=manual ← 🔴 改:manual
address1=192.168.18.130/24,192.168.18.2 ← 🟢 新增
dns=192.168.18.2;114.114.114.114 ← 🟢 新增
[ipv6]
addr-gen-mode=eui64
method=ignore
[proxy]
#使用nmcli重新刷新配置并重启网卡
nmcli conn reload # 重载配置
nmcli conn down ens160 # 断开连接
nmcli conn up ens160 # 重新连接
4. 为了便于使用常常的nmcli命令,我们可以安装bash提示包,之后使用tab可以获取命令提示
dnf install -y bash-completion
source /etc/profile.d/bash_completion.sh# 或者关闭终端重新进入
5. 如果想让网卡物理断开,请使用ip link
# 直接拔掉网卡的“电源”
ip link set ens160 down
6. nmcli/nmtui和network以及ens160物理网卡之间的关系
用户
│
▼ 发出指令 (例如: nmcli conn up ens160)
控制器 [ nmcli / nmtui ]
│
▼
管理者 [ NetworkManager 服务 (后台进程) ]
│
▼ 擦除/写入 IP,开启/关闭状态
Linux 系统内核 (Kernel) ───► 看到的效果就是 [ ip a ] 里的状态变化
│
▼
物理/虚拟网卡硬件 (ens160)
[root@localhost ~]# systemctl stop NetworkManager
[root@localhost ~]# nmcli conn down ens160
错误:网络管理器(NetworkManager)未运行。
[root@localhost ~]#


==注意==: 只要Networkmanager中断了,nmcli程序就用不了
7. nmcli命令中的up详解
[root@localhost ~]# nmcli connection add type ethernet ifname ens160 con-name dhcp_ens160 # con-name不作为唯一id,uuid是唯一区分的key
连接 "dhcp_ens160" (91641ede-2ff8-419f-84c9-09be1de79c78) 已成功添加。
[root@localhost ~]# nmcli conn show
NAME UUID TYPE DEVICE
ens160 7e7958c9-d951-3deb-af85-4459aa3dbe39 ethernet ens160
有线连接 1 80fc7e2a-c7ac-3604-939b-3cef2431af69 ethernet ens224
lo 4627f296-ae4f-43c9-9b77-b8929460b955 loopback lo
dhcp_ens160 721ec306-fde4-496c-9687-07e11a896b63 ethernet --
[root@localhost ~]# nmcli conn up 721ec306-fde4-496c-9687-07e11a896b63
连接已成功激活(D-Bus 活动路径:/org/freedesktop/NetworkManager/ActiveConnection/4)
[root@localhost ~]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: ens160: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:14:8e:67 brd ff:ff:ff:ff:ff:ff
altname enp3s0
inet 192.168.18.129/24 brd 192.168.18.255 scope global dynamic noprefixroute ens160
valid_lft 1797sec preferred_lft 1797sec
inet6 fe80::5eb6:76ae:6991:2649/64 scope link noprefixroute
valid_lft forever preferred_lft forever
3: ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 00:0c:29:14:8e:71 brd ff:ff:ff:ff:ff:ff
altname enp19s0
inet 192.168.199.128/24 brd 192.168.199.255 scope global dynamic noprefixroute ens224
valid_lft 1735sec preferred_lft 1735sec
inet6 fe80::632c:8843:174f:955a/64 scope link noprefixroute
valid_lft forever preferred_lft forever
[root@localhost ~]# nmcli connection delete dhcp_ens160
成功删除连接 "dhcp_ens160" (721ec306-fde4-496c-9687-07e11a896b63)。
==总结==:




8. MTU三层网络层数据包最大传输单元,MTU限定单IP包体积。过大丢包/分片,过小浪费带宽
网络基础知识
OSI七层模型


OSI是理论标准,TCP/IP是事实标准,五层是工程和教学的折中,更常用。每一层的唯一标识如下
数据链路层——MAC地址
网络层——IP地址传输层——端口号应用层——PID
一个就简单路由器过程示例




数据包流转每一层所干的事情


网络分层动图


tcp报文格式
![]() | ![]() |
|---|---|


使用wireshark抓取tcp数据包分析一下,按照报文格式,理解大端字节序和小端字节序。
由此可见,什么是网络协议工程师


udp和tcp对比

| 对比维度 | TCP | UDP |
|---|---|---|
| 连接状态 | 面向连接(需三次握手建立链路) | 无连接(直接发送,无需握手) |
| 可靠性 | 高(确认机制、超时重传、校验和) | 低(只做基础校验,丢包不重传) |
| 数据顺序 | 保证有序(按字节流编号,乱序重组) | 不保证(先发的可能后到,应用层自己处理) |
| 流量/拥塞控制 | 有(根据网络状况动态调整发送速度) | 无(发得快不快,完全看应用层,网络堵了照发) |
| 传输效率 | 较低(头部开销大,20字节,且需维护状态) | 极高(头部仅8字节,处理简单) |
| 收发模式 | 全双工(可同时收发) | 支持一对一、一对多、多对多(广播/组播) |
| 适用场景 | 文件传输、网页浏览、邮件、数据库 | 实时音视频、直播、在线游戏、DNS查询 |
==总结==:
关键点:
- TCP 把数据看成连续的字节流,没有”消息边界”
- 你发 3 次(100+200+50),接收端可以 1 次收完 350 字节
- 也可以分 10 次收,每次收一部分
- 发多少次 ≠ 收多少次
关键点:
- UDP 保留应用层发送的完整报文边界
- 发 3 次,收 3 次,一一对应
- 一次
recvfrom只能读到一个完整报文 - 如果接收缓冲区小于报文大小,多余数据会被丢弃
==粘包与拆包==:
TCP “粘包” 问题详解
什么是粘包?
text
发送端发了 3 次:
第一次: "Hello"
第二次: "World"
第三次: "!"
接收端 recv 一次读到: "HelloWorld!"
3 次发送,1 次收到,数据粘在一起了 → 粘包
还有”拆包”
text
发送端发一次: "HelloWorld!"
接收端 recv 两次:
第一次读到: "Hello"
第二次读到: "World!"
1 次发送,多次收到 → 拆包
统称”粘包/拆包问题”
本质原因:TCP 是流式协议,没有消息边界。
解决方案(应用层自己定边界)
| 方案 | 实现方式 | 示例 |
|---|---|---|
| 固定长度 | 每个消息固定大小 | 每次发 1024 字节,不足补 0 |
| 分隔符 | 用特殊字符分隔 | 如 HTTP 用 rnrn,用 n |
| 长度字段 | 消息头带长度 | 4 字节头 + 变长 body(最常用) |
tcp三次握手


tcp四次挥手


传输层状态查看相关命令
端口号
内核在传递网络数据包过程中,定位进程的唯一标识就是就口号,所以如果是网络服务程序,启动时必须绑定一个固定的端口号。
启动一个python server,默认端口使用了5000,也就意味着,当客户端使用curl http://192.168.18.129:5000,http应用层数据包达到linux系统后,操作系统会首先寻找监听在5000端口的应用程序,如果没有直接丢弃。如果有,再去查询绑定ip,如果进程绑定的是0.0.0.0包含所有ip,内核就将数据包交给他。如果进程绑定的是精确的ip,例如192.168.18.129,也可交个他。如果数据包目的ip与绑定的不同,丢弃。
# 指定具体的ip和端口号
[root@localhost ~]# python3.14 -m http.server -b 192.168.18.129 8080
Serving HTTP on 192.168.18.129 port 8080 (http://192.168.18.129:8080/)
# 默认启动一个server
[root@localhost ~]# python3.14 -m http.server
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
端口号理解
端口号本质上是操作系统分配给网络进程的唯一标识。当数据包通过IP地址到达你的电脑后,操作系统需要根据“端口号”来决定把数据交给哪个应用程序。
- 如果端口上有程序在监听(处于
LISTENING状态),操作系统就会把数据复制给该进程。 - 如果端口上没有程序监听,操作系统会认为没有应用需要这份数据,直接丢弃数据包,并向发送方回复一个 ICMP(互联网控制报文协议)不可达 或 RST(重置连接) 报文,表示“连接被拒绝”。
如果一个端口已经被进程 A 监听,那么进程 B 再想监听同一个端口(特别是 TCP)会报错 “Address already in use”。这保证了端口与进程的一一对应关系,也印证了“端口必须有程序监听”这一规则。
==–bind 0.0.0.0 就是你说的”通配符无论哪张网卡都会处理”,任何 IP 访问这个端口都能响应。==
最简方式:http.server 模块
1. 基本启动
bash
# 默认端口 8000,绑定所有网卡
python3 -m http.server
# 指定端口
python3 -m http.server 8080
# 指定绑定地址(0.0.0.0 表示所有网卡)
python3 -m http.server 8080 --bind 0.0.0.0
--bind 0.0.0.0就是你说的”通配符无论哪张网卡都会处理”,任何 IP 访问这个端口都能响应。
2. 指定目录
bash
# 把 /var/www/html 作为根目录
python3 -m http.server 8080 --bind 0.0.0.0 --directory /var/www/html
3. 浏览器访问
text
http://192.168.1.100:8080/
http://127.0.0.1:8080/
http://localhost:8080/
五、技术选型的取舍(Nginx 大而全 vs Python 小而轻)
- Nginx 多进程:在高并发场景下利用多核,进程数量多,资源占用高,配置复杂,适合生产级基础设施。
- Python http.server / 自写代理:单进程/单线程,性能有限,但极轻量。当业务简单(如内部调试、单点中转)且不希望被复杂的 Nginx 配置和进程管理干扰时,Python 直写是快速验证思想的最佳方案。
- 核心:脱离场景谈技术没有意义。复杂业务用 Nginx,快速验证或轻量级定制用 Python,这是工程取舍的智慧。
tcp还有重传,流量控制,滑动窗口,拥塞控制等机制,理论巨多,大家可以自行拓展,看看计算机网络相关数据
常用端口号
22(SSH)、80/443(HTTP/HTTPS)、3306(MySQL)、6379(Redis)、53(DNS)
网络相关命令
### ss(替代 netstat)
# -a, --all display all sockets
# -l, --listening display listening sockets
# -t, --tcp display only TCP sockets
# -u, --udp display only UDP sockets
# -p, --processes show process using socket
ss -tlnp # TCP 监听端口 + 进程名
ss -tulnp # TCP+UDP 监听
[root@localhost ~]# ss -tlnp
State Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=927,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=927,fd=4))
# 统计摘要
[root@localhost ~]# ss -s
Total: 131
TCP: 8 (estab 6, closed 0, orphaned 0, timewait 0)
Transport Total IP IPv6
RAW 2 0 2
UDP 4 3 1
TCP 8 7 1
INET 14 10 4
FRAG 0 0 0
# lsof
# -i select IPv[46] files, 读取ip相关的运行时文件
lsof -i :8080 # 谁在用 8080
lsof -i tcp:3306 # MySQL 谁在监听




































































































































































