Linux systemd.socket ListenDatagram 怎样监听 UDP 套接字
想要用Linux systemd.socket的ListenDatagram监听UDP套接字,操作逻辑很清晰,你只需要创建对应.socket单元,在配置项里声明UDP类型的监听目标,关联绑定实际运行的服务单元,systemd就会提前完成套接字创建,再把收到的UDP报文交给对应业务进程处理。
只要正确配置ListenDatagram字段指定监听端口、IP或套接字文件路径,搭配对应设置了Accept=yes或关联服务的socket单元,就能完成UDP套接字监听,同时还能获得systemd托管的套接字常驻能力,服务崩溃重启也不会出现UDP端口长时间空窗的问题。
如果要让 systemd 负责创建 UDP 监听套接字,再按需启动一个处理程序,关键配置是 ListenDatagram=。它对应 SOCK_DGRAM,而不是 TCP 的 ListenStream=;对于 IP 地址,systemd 会先完成绑定,再把监听套接字交给匹配的服务。服务因此不应该再次对同一个地址调用 bind()。
官方地址:https://www.freedesktop.org/software/systemd/man/latest/systemd.socket.html
最小可用方案是:在.socket文件的[Socket]段写入ListenDatagram=127.0.0.1:9125,让同名.service从 systemd 传入的文件描述符读取数据报。UDP 场景不需要用Accept=yes为每个数据报创建服务实例。
先分清 ListenDatagram 和 ListenStream
ListenDatagram= 表示数据报套接字,IP 场景对应 UDP;ListenStream= 表示流式套接字,IP 场景对应 TCP。两者都可以触发服务,但应用读取方式和生命周期不同:UDP 保留一条条数据报的边界,TCP 则是连续字节流。
| 配置项 | IP 套接字类型 | 本文是否使用 |
|---|---|---|
ListenDatagram= | UDP / SOCK_DGRAM | 是,服务用 recvfrom() 读取 |
ListenStream= | TCP / SOCK_STREAM | 否,不能用来替代 UDP |
Accept= | 主要影响连接型套接字 | UDP 数据报场景下被忽略 |
编写 socket unit:让 systemd 创建 UDP 套接字
假设服务只在本机的 127.0.0.1:9125 接收数据报,先创建 /etc/systemd/system/udp-demo.socket:
[Unit]
Description=UDP demo socket
[Socket]
# 由 systemd 绑定本机 UDP 端口,服务不再重复 bind
ListenDatagram=127.0.0.1:9125
# 显式写出服务名,便于 unit 改名后仍保持关联
Service=udp-demo.service
[Install]
# 让管理员可以用 systemctl enable 启用这个 socket
WantedBy=sockets.target
如果省略 Service=,systemd 默认会寻找同名的 udp-demo.service。显式配置的好处是 unit 文件名和实际服务名不一致时,关联关系仍然清楚。

让服务从 fd 3 读取数据报
systemd 的原生 socket passing 会把监听套接字传给服务。常见约定是第一个激活套接字从文件描述符 3 开始,环境变量 LISTEN_FDS 表示数量,LISTEN_PID 用来确认这些描述符属于当前进程。
下面的 Python 示例只展示接收边界。它假定解释器和脚本路径已经由管理员准备好,代码不创建 UDP 监听端口,也不包含真实业务处理:
import os
import socket
# 只接受 systemd 传入的一个监听描述符,避免误把普通启动当成激活启动。
if os.environ.get("LISTEN_FDS") != "1":
raise RuntimeError("需要 systemd 传入一个 UDP 文件描述符")
# systemd 的第一个监听描述符从 3 开始;这里不重复 bind 地址和端口。
udp_socket = socket.fromfd(3, socket.AF_INET, socket.SOCK_DGRAM)
try:
while True:
# recvfrom 保留每个 UDP 数据报的边界,同时返回发送方地址。
payload, peer = udp_socket.recvfrom(4096)
print(f"收到 {peer} 的 {len(payload)} 字节数据")
finally:
# fromfd 会复制一个 Python 文件描述符,退出前关闭这份引用。
udp_socket.close()
生产服务还应处理退出信号、日志和异常;这里的重点是接口边界:服务接收由 systemd 已经创建好的套接字,不要把 127.0.0.1:9125 再交给 bind()。

配置对应的 service unit
在同一目录创建 /etc/systemd/system/udp-demo.service:
[Unit]
Description=UDP demo service
Requires=udp-demo.socket
After=udp-demo.socket
[Service]
Type=simple
# 该脚本读取 systemd 传入的 fd 3,不在进程内创建监听端口
ExecStart=/usr/bin/python3 /opt/udp-demo/server.py
Restart=on-failure
[Install]
WantedBy=multi-user.target
Requires= 和 After= 表达的是服务与 socket unit 的依赖和顺序关系。socket unit 触发服务时,systemd 会把已经创建的套接字交给它;服务自己直接启动时,也要能正确处理 socket 不存在或未被激活的情况。
启用后怎样判断配置是否生效
配置文件保存后,先让 systemd 重新读取 unit,再启用并启动 socket:
# 重新读取 unit 文件,避免继续使用旧配置
sudo systemctl daemon-reload
# 让 socket 在启动目标中启用,并立即开始监听
sudo systemctl enable --now udp-demo.socket
# 查看 socket 的监听地址和关联服务
systemctl status udp-demo.socket
# 查看 unit 的完整属性,便于确认 ListenDatagram 和 Service
systemctl show udp-demo.socket -p Listen -p Service -p ActiveState
可见的成功条件是:udp-demo.socket 处于 active 状态,状态信息中能看到 127.0.0.1:9125,并且 Service 指向 udp-demo.service。向该端口发送一个 UDP 数据报后,服务应被激活并在日志中出现接收记录。
# 只发送一条本机测试数据报,不改变 socket unit 配置
printf 'hello systemd\n' | nc -u -w1 127.0.0.1 9125
# 查看本次服务激活产生的日志
journalctl -u udp-demo.service -n 20 --no-pager
四个容易误用的配置边界
Accept=yes 不是 UDP 并发开关
systemd 文档明确说明,Accept= 对数据报套接字会被忽略;UDP 由一个服务单元处理传入数据报。不要把 TCP 的每连接实例模型直接套到 UDP 上。
Backlog 不负责 UDP 数据报排队
Backlog= 影响尚未接受的流式或顺序分组连接,对本文的 UDP 数据报监听不是主要配置项。UDP 的接收缓冲、丢包和应用读取速度应从对应的 socket 与系统参数另行分析。
监听地址决定暴露范围
127.0.0.1:9125 只在本机回环地址监听;如果改成某个具体网卡地址,服务可达范围会随网卡和路由变化;如果改成通配地址,则应同时评估防火墙和访问控制。不要为了“先跑起来”盲目改成所有接口。
服务不要重复绑定
socket activation 的职责分工是 systemd 创建并持有监听套接字,服务读取并消费它。服务再次调用 bind(),通常会得到地址已被占用的错误,即便打开了某些复用选项,也会把职责和排障路径弄复杂。
结论与延伸问题
要用 Linux systemd.socket 监听 UDP,记住三件事:用 ListenDatagram=地址:端口 声明 SOCK_DGRAM,让匹配的 service 从 fd 3 接收套接字,并用 socket unit 的状态确认监听地址和服务关联。Accept=、Backlog= 不能替代 UDP 的接收模型;地址范围和服务是否重复 bind 才是最常见的排错重点。
相关问题:
- 如果服务启动后看不到 fd 3,先检查
LISTEN_FDS是否为 1,以及 service 是否确实由 socket unit 触发。 - 如果端口被占用,先确认是否还有其他进程或旧 unit 绑定了同一地址,不要立即增加复用选项。
- 如果要监听 TCP,应改用
ListenStream=并重新设计服务的读取循环。
Linux rsync 部分传输后的断点续传参数
- 上一篇
- Linux rsync 部分传输后的断点续传参数
- 下一篇
- Linux perf record 采样权限与调用栈配置
-
- 文章 · linux | 40分钟前 | Linux · Linux tmpfiles.d systemd-tmpfiles 临时目录清理
- Linux tmpfiles.d 临时目录清理规则的部署
- 223浏览 收藏
-
- 文章 · linux | 41分钟前 |
- Linux vmstat 指标与 I/O 等待的判断
- 225浏览 收藏
-
- 文章 · linux | 44分钟前 |
- Linux perf record 采样权限与调用栈配置
- 301浏览 收藏
-
- 文章 · linux | 49分钟前 | linux运维 · Linux Rsync 断点续传 partial-dir append-verify
- Linux rsync 部分传输后的断点续传参数
- 108浏览 收藏
-
- 文章 · linux | 50分钟前 |
- Linux tar 排除规则与目录层级的打包
- 434浏览 收藏
-
- 文章 · linux | 52分钟前 | Linux ·
- Linux nftables 集合规则的批量维护
- 112浏览 收藏
-
- 文章 · linux | 52分钟前 |
- Linux find 按时间与大小组合筛选文件
- 404浏览 收藏
-
- 文章 · linux | 56分钟前 |
- Linux ip 命令查看策略路由命中顺序
- 118浏览 收藏
-
- 文章 · linux | 56分钟前 |
- Linux systemd RestrictAddressFamilies 怎样限制服务使用的网络协议族
- 117浏览 收藏
-
- 文章 · linux | 1小时前 |
- Linux systemd-escape 怎样把路径转换成实例化 unit 名称
- 382浏览 收藏
-
- 文章 · linux | 1小时前 | 定时器 · Linux · 运维 · 服务管理 · Linux 定时任务 OnCalendar 单调时间 systemd.timer OnBootSec
- Linux systemd.timer 日历与单调时间的选择
- 430浏览 收藏
-
- 文章 · linux | 1小时前 |
- Linux systemd.path 监听文件变化的触发配置
- 123浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 485次学习
-
- PubMedQA
- 深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
- 755次使用
-
- H2O EvalGPT
- H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
- 753次使用
-
- LMArena
- LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
- 834次使用
-
- HELM
- 深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
- 800次使用
-
- MMBench
- MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
- 634次使用
-
- Linux vmstat 如何分辨内存抖动与磁盘等待:si、so、wa 与复测顺序
- 2026-08-30 501浏览
-
- Linux搭建vsftpdFTP服务器教程
- 2026-04-30 501浏览
-
- Shell脚本安装教程:.sh一键安装指南
- 2026-03-16 501浏览
-
- Linux清空文件内容的几种方法
- 2025-12-01 501浏览
-
- Linux命令行下载文件技巧
- 2025-11-23 501浏览

