当前位置:首页 > 文章列表 > 文章 > linux > Linux systemd.socket ListenDatagram 怎样监听 UDP 套接字

Linux systemd.socket ListenDatagram 怎样监听 UDP 套接字

来源:17golang原创 2026-10-28 13:31:51 0浏览 收藏

想要用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 文件名和实际服务名不一致时,关联关系仍然清楚。

socket unit、ListenDatagram、UDP套接字和服务单元的静态关系图
图1:ListenDatagram 配置结构图,展示 socket unit 如何声明 UDP 地址并关联服务单元。

让服务从 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()。

LISTEN_FDS、fd3、socket.fromfd和UDP服务循环的静态关系图
图2:文件描述符交接结构图,展示服务如何从 systemd 接收 fd 3 并读取 UDP 数据报。

配置对应的 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= 并重新设计服务的读取循环。
版本声明
本文转载于:17golang原创 如有侵犯,请联系study_golang@163.com删除
Linux rsync 部分传输后的断点续传参数Linux rsync 部分传输后的断点续传参数
上一篇
Linux rsync 部分传输后的断点续传参数
Linux perf record 采样权限与调用栈配置
下一篇
Linux perf record 采样权限与调用栈配置
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    543次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    516次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    500次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    485次学习
查看更多
AI推荐
  • PubMedQA数据集详解:生物医学问答基准、功能与应用指南
    PubMedQA
    深入了解PubMedQA生物医学问答数据集,涵盖其核心功能、使用方法及在临床决策、药物研发等场景的应用,助力提升NLP模型性能。
    755次使用
  • H2O EvalGPT:开源LLM大模型评估与排行榜工具
    H2O EvalGPT
    H2O EvalGPT是H2O.ai推出的开源LLM评估平台,提供详细的大模型性能排行榜、行业特定基准测试及A/B测试功能,助您快速选择最适合项目的高性能大语言模型。
    753次使用
  • LMArena是什么?伯克利AI模型评估平台使用指南与功能解析
    LMArena
    LMArena是加州大学伯克利分校推出的AI模型匿名评测平台。通过盲测投票机制,用户可对比不同大模型回答并生成实时排行榜,助力开发者优化模型及用户选择最佳AI工具。
    834次使用
  • 斯坦福HELM:大语言模型Holistic Evaluation整体评估框架详解
    HELM
    深入了解斯坦福推出的HELM(Holistic Evaluation of Language Models)大模型评测体系。本文解析其核心功能、安装配置步骤及应用场景,涵盖准确性、公平性、鲁棒性等多维度指标,助力开发者全面优化语言模型性能。
    800次使用
  • MMBench详解:多模态大模型基准测试、功能特点与使用指南
    MMBench
    MMBench是由上海人工智能实验室等机构联合推出的多模态基准测试平台,提供细粒度能力评估、大规模数据集及VLMEvalKit工具。本文详细介绍其核心功能、安装使用方法及应用场景,助力开发者全面评估多模态模型性能。
    634次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议 和 隐私政策
返回登录
  • 重置密码