UDP Socket编程
搞清socket()到IOCP每层API背后的真实行为与边界
按 空格/→ 演示下一步
全部页面点击任意一页,跳回舞台从这页播放
UDP Socket编程
搞清socket()到IOCP每层API背后的真实行为与边界
UDP协议与Socket的关系
上一页你用 socket(AF_INET, SOCK_DGRAM, ...) 收发数据报时,有没有想过:Socket 到底是什么?它和 UDP 协议是同一个东西吗?
投信到邮筒(sendto),邮政(UDP)送达;对端从邮筒取信(recvfrom)。邮筒是接口
UDP无连接通信模型
从左到右是一条数据报的完整生命周期:客户端 sendto → 无连接直接发送 → 网络独立传输 → 服务端 recvfrom。
UDP Socket地址结构
上一页说 UDP 发数据要指定「发给谁、哪个端口」。落到 C 代码,这个「谁」不是一个字符串,而是一个结构体。它叫什么、每个字段又存什么?这页拆开看。
family=走哪个国家邮政,port=门牌号,addr=街道地址,zero=信封统一尺寸的填料
UDP客户端代码框架
用 Python 演示 UDP 客户端四步:建 socket、发数据、收响应、关 socket。
SOCK_DGRAM 标识 UDP;sendto 因无连接必须带目标地址;recvfrom 同时返回数据与来源;close 释放 socket。
UDP服务器端代码框架
一段真实可跑的 Windows Winsock UDP 服务器,串起 socket→bind→recvfrom→sendto→close 整条主流程。
对照流程看:socket 拿句柄→bind 占端口→recvfrom 同时取数据和对方地址→sendto 用同一地址回写→close 收尾,这正是无连接 UDP 服务器的最小骨架。
关键函数参数详解
前面我们已经搭好了客户端和服务器端的代码骨架,但骨架只告诉你函数怎么摆位——真正决定程序健壮性的,是 sendto 和 recvfrom 每个参数的含义,以及返回值告诉你的事。
快递单的发件人、收件人、重量、物品都对应参数,地址写错或漏填长度就寄不到
UDP程序编译运行
从代码到运行:gcc 编译 UDP 程序并本地验证通信。
UDP常见错误与对策
上一节你们跑通了 UDP 程序,但很可能第一次 bind 就报错,或者客户端发完消息什么回执也没收到——这些都不是逻辑写错,而是 UDP 编程里几个典型的'坑'。
首次听到'号码不存在',之后运营商只默默挂断
UDP调试工具使用
UDP问题分两层排查:先netstat看本地socket状态,再抓包看网络层真实流量,从本地逻辑走到物理抓包逐步缩小范围。
TCP协议与Socket的关系
UDP那页讲过——发出去就不管。TCP反过来:发出去必须确认收到、丢了重发、按序到达。这么复杂的可靠性机制,是怎么让几行代码就能享受到的?靠的就是Socket。
你只管寄件和签收;中途丢件、错路、重发都由快递系统兜底
TCP面向连接通信模型
TCP通信分三阶段:三次握手建连、数据传输、四次挥手释放,自上而下按时序推进。
TCP三次握手原理
UDP像寄平信,写完地址就扔出去,不管对方在不在。TCP不一样——它必须先确认双方「收发都通畅」才会传数据,这套协商机制就是三次握手。
一方问「能听到吗?我是A」;另一方答「能,我是B」;一方再说「收到,开始聊」
TCP四次挥手原理
三次握手建立连接是双向确认,那关闭连接也得双向确认——两边各自独立关掉发送方向才算结束。所以挥手需要四次信号,而不是三次。
一方说『不说了』,对方回『好』;等对方也说完再回『再见』,才彻底挂断
TCP Socket地址结构
三次握手解决的是「连接怎么建」,但客户端得先知道连哪台机器、哪个端口,服务器也得指明自己挂在哪个地址上。把这些信息封装起来的,就是 sockaddr_in。
family=国家编码、port=门牌号、addr=街道地址,都得填对才能送达
TCP客户端代码框架
从初始化到关闭,TCP客户端的六个标准步骤一目了然。
WSAStartup→socket→connect→send/recv→closesocket,对应TCP面向连接的完整生命周期。
TCP服务器端代码框架
一段最小可跑的C代码,串起socket→bind→listen→accept→recv/send→close六步流程。
六行高亮严格对应大纲六步流程。进阶要点:socket()返回的是监听fd,accept()返回的是连接fd;二者各有独立生命周期,必须分别close,漏一个就是经典资源泄漏。
listen与accept的机制
前台接待最清楚这过程:酒店开门营业(listen),门口摆几张等候椅(backlog),客人到了就由前台带一位进房间(accept),前台转身继续迎接下一位。
listen=开门+摆等候椅,accept=带一位进房间,原前台继续接下一位
TCP字节序转换
上页代码里,sin_port 和 sin_addr.s_addr 都用了 htons、htonl。端口和 IP 是整数,为什么不能直接赋值?这两个函数做了什么?
寄件人按自己习惯装箱,快递公司规定统一标准打包,收件人再按自己习惯拆开
TCP程序编译运行
多客户端场景下,TCP程序的编译与测试需要按顺序配合:服务端先就位,再让多个客户端连上去验证并发。
TCP常见错误与对策
程序终于跑通——可这只是开始。真实网络里 connect、bind、recv 时不时崩出一行让人查半天的错误。这一页把高频错误码和它们的来历摆到桌面。
没人应门、被赶走、敲太久没人回——对应不同错误码的不同故事
TCP调试工具使用
从抓包到分析,五步走完TCP流量调试。箭头即数据流向,方框即工具动作。
UDP vs TCP核心特性对比
UDP和TCP常被混用,但本质是两种相反的传输哲学——速度vs可靠。
- 无连接:发包前不需要握手
- 不可靠:不保证送达、顺序、去重
- 头部8字节,开销极小
- 适用实时:丢一帧不致命
- 面向连接:必须三次握手
- 可靠传输:重传、排序、去重
- 头部≥20字节,控制字段多
- 适用准确:错一字节就出错
协议选择决策树
从起点向下按四道判断条件走,Yes 分支汇向 TCP,No 继续下沉直至落到 UDP。
UDP与TCP核心理解
TCP 客户端连续两次 send() 各发 100 字节,服务端两次 recv() 接收,最可能发生什么?
Socket编程知识总结
- ✓UDP 的"简陋"是设计取舍,应用层补足可靠性
- ✓TCP 是字节流不是消息流,必须自己分包
- ✓listen 建队列,accept 才完成握手
- ✓网络字节序大端,跨平台必须显式转换
- ✓协议选择是实时性、可靠性与复杂度的权衡
课后思考
先自己想 30 秒,再点开参考答案——这是思考路径,不是标准答案。
参考答案UDP 是无连接的——每次 sendto 都是一次独立投递,不需要"挂牌迎客"。TCP 必须先建立专属通道(三次握手 + accept),才能在这条通道上可靠收发。
参考答案TCP 的重传保证"字节不丢",但代价是延迟累积:一个包丢就阻塞后续。UDP 把丢包和乱序交给你处理,对实时画面而言,丢一帧远好过卡三秒等重传。
参考答案不会。客户端发 SYN 后启动重传计时器(约 1 秒),收不到第二个 SYN+ACK 就重发 SYN,重试若干次后放弃报错。SYN flood 攻击正是利用这一点耗尽服务器资源。