嵌入式操作系统 | UDP 服务器编程模块四 · 2 学时 · 环境VMware Ubuntu 20.04一句话概述用 C 写一个 UDP 服务器socket / bind / recvfrom / sendto 回包讲清服务器为什么必须 bind、INADDR_ANY 是什么意思并用 Python 写的测试客户端发包验证文档给出启动顺序、命令与运行结果配套课堂练习与课后作业。本节目标能说出服务器和客户端的区别解释服务器为什么必须 bind会用 socket / bind / recvfrom / sendto 写出一个收包并回包的 UDP 服务器会先把 C 服务器跑起来再用 Python 工具发包测试并会用ss确认端口在监听一、讲解内容1.1 知识讲解服务器与客户端的区别。客户端是主动去发的一方服务器是一直等着收的一方。上节课的客户端不写 bind系统自动给临时端口而服务器必须 bind 到固定的端口因为别人只有知道端口才能找到它——就像快递必须有个固定地址。服务器四步步骤函数在干嘛1socket(AF_INET, SOCK_DGRAM, 0)创建 UDP 套接字2bind(...)绑定自己的 IP 和端口之后别人才能发数据给你3recvfrom(...)收数据它会把是谁发的对方的 IP 和端口一起带回来4sendto(...)用第 3 步带回来的对方地址把结果回过去INADDR_ANY是什么。bind 时填htonl(INADDR_ANY)等于 0.0.0.0意思是本机所有网卡都收不管是 127.0.0.1 还是虚拟机网的 192.168.x.x只要有包发到这个端口服务器都收得到。如果只绑127.0.0.1那只有本机自己能连上。为什么可以一直循环收。服务器写成while (1) { recvfrom ... sendto ... }没有包时recvfrom会睡着不占 CPU来一个包就处理一个。这就是最朴素的网络服务模型下节课的 TCP 服务器也用这个思路只是多了连接管理。为什么服务器也要能回包。实际项目里客户端发完数据往往要等一个收到的确认这样才知道数据没丢。本课让服务器回一句服务器已收到 N 字节xxx方便你在客户端那侧直接看到效果。1.2 怎么运行两个终端服务器先开、测试工具后开终端 AC 服务器 终端 BPython 测试客户端 ① 第 1 个启动打印已启动 ──────► ② 看到启动信息后再发包 ③ 打印收到的每个包 ③ 打印已发送/收到的回复 ④ 按 CtrlC 停止 ④ 发完自动退出第 1 步在终端 A 编译并启动 C 服务器先做这一步gcc-Wall-Wextra-gudp_server.c-oudp_server# 编译无输出成功./udp_server9999# 启动监听 9999 端口看到这一行才算启动成功UDP 服务器已启动监听 9999 端口按 CtrlC 退出第 2 步在终端 B 确认端口在监听不是必须但很有用出问题时靠它定位ss-ulnp|grep9999正常会看到类似udp UNCONN 0 0 0.0.0.0:9999 0.0.0.0:*的输出说明端口已经打开。第 3 步在终端 B 用 Python 工具发包服务器开着的时候才做python3 udp_sender.py127.0.0.199993# 发 3 条并等回复第 4 步对照两个终端的输出本机真实运行结果。终端 BPython 测试客户端已发送: sensor-1: 温度 21.5 C 收到回复: 服务器已收到 23 字节sensor-1: 温度 21.5 C 已发送: sensor-2: 温度 22.5 C 收到回复: 服务器已收到 23 字节sensor-2: 温度 22.5 C 已发送: sensor-3: 温度 23.5 C 收到回复: 服务器已收到 23 字节sensor-3: 温度 23.5 C 测试结束终端 AC 服务器UDP 服务器已启动监听 9999 端口按 CtrlC 退出 收到 127.0.0.1:37085 的 23 字节sensor-1: 温度 21.5 C 收到 127.0.0.1:37085 的 23 字节sensor-2: 温度 22.5 C 收到 127.0.0.1:37085 的 23 字节sensor-3: 温度 23.5 C一边发、一边收两边的字节数一样就说明服务器工作正常。第 5 步再玩两个花样。① 用客户端来测如果课时 11 的 C 客户端还在./udp_client 127.0.0.1 9999 你好也能收到本课服务器的回包② 故意先把服务器 CtrlC 停掉再用 Python 发包会看到每条都打印2 秒内没有收到回复——这就是服务器没开的现象。第 6 步收工。回到终端 A 按CtrlC停服务器。顺序口诀服务器先开、测试工具后开服务器最后关。1.3 常见错误与排查现象原因解决bind端口被占用...: Address already in use上一次的服务器没关端口被占着CtrlC停掉旧的或换个端口如 88882 秒内没有收到回复服务器没启动或端口不一致先看终端 A 有没有打印已启动再核对端口号本机能通别的机器发不进来绑到了127.0.0.1用htonl(INADDR_ANY)绑所有网卡permission denied用了 1024 以下的端口如 80换 1024 以上的端口本课用 9999服务器收到乱码客户端发的不是 UTF-8统一用 UTF-8 编码发送和显示二、学生练习本节命令速查表命令作用示例gcc 源文件 -o 程序编译 C 服务器gcc -Wall -Wextra -g udp_server.c -o udp_server./udp_server 端口启动服务器终端 A先开./udp_server 9999ss -ulnp | grep 端口查看 UDP 端口监听情况ss -ulnp | grep 9999python3 udp_sender.py IP 端口 条数用 Python 工具发包终端 Bpython3 udp_sender.py 127.0.0.1 9999 3CtrlC停止服务器在终端 A 按编号任务提示预期结果L12.1按文档跑通一次先服务器、后发包两个终端注意顺序服务器打印 3 个包客户端收到 3 条回复L12.2换端口 8888 再来一次服务器参数和 Python 参数都要改依然收发成功L12.3停掉服务器再发包先按 CtrlC再运行 Python每条都提示2 秒内没有收到回复L12.4用ss看监听状态启动服务器前后各执行一次启动后能看到 9999 端口L12.5服务器改成回包内容不同例如回OK改snprintf那一行重新编译客户端收到的回复变成新的内容L12.6和课时 11 的 C 客户端联调服务器本课写的客户端用课时 11 的两边输出互相对应三、作业必做完成 L12.1、L12.4提交两个终端截图服务器输出 Python 客户端输出与ss -ulnp | grep 9999的截图并回答① 服务器为什么必须 bind客户端为什么不用②INADDR_ANY是什么意思选做把服务器改成收到什么就原样回什么回显服务器再和课时 11 的客户端互测提交截图 文字回答命名课时12-作业截图.png四、本节小结与下节预告本节写出了 UDP 服务器socket → bind → 循环 recvfrom → sendto 回包并学会用ss检查端口、用 Python 工具当客户端做测试再次确认了服务先开、测试后开的顺序。下节进入 TCP同样是客户端但先要connect完成三次握手可靠但不丢数据。附录怎么运行 完整代码一个课件就够用先看附录 A 的运行顺序服务端先开、客户端后开再把附录 B/C 的代码按文件名新建到同一个目录里。行尾请用 LF。附录 A怎么编译运行注意先后顺序# 编译 C 服务器gcc-Wall-Wextra-gudp_server.c-oudp_server# 第 1 步终端 A 先启动服务器必须先做不能颠倒./udp_server9999# 看到 UDP 服务器已启动监听 9999 端口 才算成功ss-ulnp|grep9999# 可选确认端口在监听# 第 2 步终端 B 用 Python 工具发包并等回复python3 udp_sender.py127.0.0.199993# 第 3 步对照两个终端的输出# 收工回到终端 A 按 CtrlC 停止服务器附录 B文件udp_server.c/* * udp_server.c —— 课时 12UDP 服务器收包 → 打印 → 回包 * * 编译gcc -Wall -Wextra -g udp_server.c -o udp_server * 运行./udp_server # 默认监听 9999 端口 * ./udp_server 8888 # 也可以指定端口 */#includestdio.h#includestdlib.h#includestring.h#includestdint.h#includeunistd.h#includearpa/inet.h#includesys/socket.h#defineBUF_SIZE512intmain(intargc,char*argv[]){intsock;intport9999;charbuf[BUF_SIZE];charreply[BUF_SIZE32];structsockaddr_inaddr;structsockaddr_inpeer;socklen_tpeer_lensizeof(peer);ssize_tn;if(argc2){portatoi(argv[1]);}/* 1. 创建 UDP 套接字 */socksocket(AF_INET,SOCK_DGRAM,0);if(sock0){perror(socket);return1;}/* 2. 绑定自己的地址和端口服务器必须 bind客户端不用 * INADDR_ANY 表示本机所有网卡0.0.0.0都收包 */memset(addr,0,sizeof(addr));addr.sin_familyAF_INET;addr.sin_addr.s_addrhtonl(INADDR_ANY);addr.sin_porthtons((uint16_t)port);if(bind(sock,(structsockaddr*)addr,sizeof(addr))0){perror(bind端口被占用换个端口试试);close(sock);return1;}printf(UDP 服务器已启动监听 %d 端口按 CtrlC 退出\n,port);fflush(stdout);/* 输出重定向到文件时是块缓冲不刷新就看不到 *//* 3. 循环收包recvfrom 会告诉我们是哪一个客户端发来的 */while(1){memset(buf,0,sizeof(buf));nrecvfrom(sock,buf,sizeof(buf)-1,0,(structsockaddr*)peer,peer_len);if(n0){perror(recvfrom);continue;}printf(收到 %s:%d 的 %zd 字节%s\n,inet_ntoa(peer.sin_addr),ntohs(peer.sin_port),n,buf);fflush(stdout);/* 实时看到收到的包 *//* 4. 回一句话给客户端地址用 recvfrom 带回来的 peer */snprintf(reply,sizeof(reply),服务器已收到 %zd 字节%s,n,buf);if(sendto(sock,reply,strlen(reply),0,(structsockaddr*)peer,peer_len)0){perror(sendto);}}close(sock);return0;}附录 C文件udp_sender.py#!/usr/bin/env python3课时 12 测试工具UDP 测试客户端给 C 服务器发包并等回复 用法python3 udp_sender.py [IP] [端口] [条数] 例python3 udp_sender.py 127.0.0.1 9999 3 importsocketimportsysimporttime ipsys.argv[1]iflen(sys.argv)1else127.0.0.1portint(sys.argv[2])iflen(sys.argv)2else9999countint(sys.argv[3])iflen(sys.argv)3else3ssocket.socket(socket.AF_INET,socket.SOCK_DGRAM)s.settimeout(2)foriinrange(1,count1):msgfsensor-{i}: 温度{20i}.5 Cs.sendto(msg.encode(),(ip,port))print(f已发送:{msg})try:data,addrs.recvfrom(1024)print(f收到回复:{data.decode(utf-8,replace)})exceptsocket.timeout:print(2 秒内没有收到回复)time.sleep(0.5)s.close()print(测试结束)
企业数字化 ERP 产品动态
相关推荐
ST Model Zoo还是自研模型?嵌入式AI模型设计的实用指南 上周一个做嵌入式的朋友问我:ST 官方已经放出了 Model Zoo,里面现成的模型一大堆,我们真的还需要自己设计模型吗? 我没有直接回答,而是反问他:你的目标芯片是哪个,数据长什么样,精度… · 2026/9/26 2:16:16
Fathom Lite 升级指南:二进制替换、版本校验与 Web 服务器重启 数据分析后端 【免费下载链接】fathom Fathom Lite. Simple, privacy-focused website analytics. Built with Golang & Preact. 项目地址: https://gitcode.com/gh_mirrors/fa/fathom 点击查看 免费下载 本篇技术指南面向自托管 Fathom Lite 网站分析服务的运… · 2026/9/26 2:16:16
IOPaint 安装教程:15 分钟在 Windows 上免费跑起 AI 消除工具 IOPaint 安装教程:15 分钟在 Windows 上免费跑起 AI 消除工具 【免费下载链接】IOPaint Image inpainting tool powered by SOTA AI Model. Remove any unwanted object, defect, people from your pictures or erase and replace(powered by stable diffusion) any… · 2026/9/26 2:16:16
公网组网安全怎么做?SD-WAN安全防护要点与落地实践 1. 为什么公网组网绕不开 SD-WAN 安全这道坎我这两年帮不少企业做过组网项目,发现一个挺现实的规律:只要涉及到跨地域、跨分支机构的互联,大家第一反应就是走公网。成本低、部署快、哪里都能通,确实是最省事的路径。但公网的另一个… · 2026/9/26 4:22:48
AI 提问建议(Prompt Suggestions)的动态流式弹出 AI 提问建议(Prompt Suggestions)的动态流式弹出在对话交互系统中,用户很多时候并不知道下一句该问什么。大语言模型输出完一长串技术分析或操作方案后,页面若只是死寂地停留在光标闪烁状态,交互回路就出现了断崖式的冷… · 2026/9/26 4:22:42
16k业务语义协议:用16个字段定义可验证、可执行的业务规则 1. 这不是又一个文档生成器,而是一次业务语言的“协议层”重建你有没有经历过这样的场景:产品同学在飞书文档里写了30页PRD,开发拿到后第一句话是“这个‘用户点击按钮后触发校验’,到底是前端校验、后端校验,还是两者… · 2026/9/26 4:22:42
离线生成与实时生成的混合策略:平衡生成成本与游戏响应度 离线生成与实时生成的混合策略:平衡生成成本与游戏响应度在游戏工业界引入 AIGC(文本、纹理、语音、关卡、NPC 行为)的过程中,不少团队容易走向两个极端:要么试图将所有内容全部依赖云端大模型实时生成(导致… · 2026/9/26 4:22:42
轻量级Web开发实战:WorkBuddy+Flask+SQLite快速搭建失物招领平台 1. 为什么我放弃了重型CMS,转投WorkBuddyFlaskSQLite这套轻量组合去年年底我接手了一个校园失物招领平台的搭建需求,甲方给的时间窗口只有两周,要求能本地部署、支持信息发布、还得带智能匹配推荐。我第一反应是上WordPress——毕竟生态成熟、… · 2026/9/26 4:22:42
入职背调一般要多久?时长决定因素与高效提速指南 入职背调一般要多久?这个问题几乎每个候选人面试通过后都会问一遍。我的答案是:多数情况下3到7个自然日,最快的1到2天就能完成,慢的拖到两周以上也是常事。落差这么大,是因为背调的时长根本不取决于“背调公司想不想快… · 2026/9/26 4:22:42
数据库课后习题答案别硬背:当测试用例集刷,效率翻倍 简介:万常选版《数据库原理与设计》课后习题答案资源,覆盖第2至6章及第9章,适合正在学习关系模型、数据库建模、关系数据理论与模式求精的本科生、自学者作为复习与自测材料。压缩包共7个文件,含3个doc参考答案、2个sql示例脚本、… · 2026/9/26 0:00:21
OpenClaw 替代品?Hermes Agent 踩坑实录:macOS 飞书接入 TaoToken 配置 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/26 0:00:40
向下兼容与向上兼容:接口设计中的兼容性策略与工程实践 一次版本升级事故,是很多团队绕不过去的坎。线上环境里,服务端明明已经上线了新版接口,老的移动端还在照着旧文档传参数。请求一到网关,校验直接拒绝,用户操作失败,客服群炸了锅,开发群里开始互… · 2026/9/26 0:00:46