本篇总结
使用 W6300 的硬件 TOE 引擎实现 UDP 数据回环测试,支持 IPv4/IPv6 双协议栈。
🔑 MH2457、QSPI、UART调试、硬件TOE引擎、UDP、DHCP
硬件平台 :本例程基于 W6300-EVB-M4 开发板运行。
采购推荐 :点击前往 WIZnet 官方淘宝店铺 选购 W6300-EVB-M4 开发板
本示例演示使用 W6300 的硬件 TOE 引擎实现 UDP 数据回环测试。核心是基于 Socket 状态机的 loopback_udps() 函数,在 SOCK_CLOSED → SOCK_UDP 状态间切换,通过 recvfrom()/sendto() 收发数据并自动获取对端地址,实现无需连接的 UDP 数据回环。W6300 支持 IPv4/IPv6 双协议栈,UDP Socket 可配置为 UDP4、UDP6 或双栈模式。
前置工具准备
开始本例程前,请确认以下工具已安装:
WIZ UartTool V1.0 :串口调试工具:点击下载
SocketTester :网络调试工具:点击下载
UDP 协议简介
UDP(User Datagram Protocol)是一种无连接的、不可靠的传输层协议。与 TCP 不同,UDP 不需要建立连接,直接发送数据报文,具有开销小、延迟低的特点。UDP 不保证数据到达、不保证顺序、不保证完整性,但传输效率高,适合实时音视频、DNS 查询、SNMP 等对实时性要求高但对可靠性要求不严格的场景。
无连接: 无需三次握手,直接发送数据报文
不可靠: 不保证数据到达,不保证顺序,无重传机制
高效率: 无连接建立开销,头部仅 8 字节(TCP 为 20 字节)
支持广播/组播: 可向多个目标同时发送数据
recvfrom()/sendto(): 收发数据时自动获取/指定对端地址
对比项 UDP TCP
连接方式 无连接 面向连接(三次握手)
可靠性 不可靠,无重传 可靠,自动重传
头部开销 8 字节 20 字节
传输效率 高 较低(确认/重传开销)
Socket状态 SOCK_UDP SOCK_INIT/ESTABLISHED等
收发API recvfrom/sendtorecv/send
W6300 的 UDP 优势
W6300 的 TOE 引擎硬件支持 UDP 协议,UDP 报文的封装、校验、分片等全部在硬件内部完成。用户只需调用 socket(sn, Sn_MR_UDP4, port, SOCK_IO_NONBLOCK) 打开 UDP Socket,然后通过 recvfrom()/sendto() 收发数据,无需关心 UDP 协议细节。W6300 支持 IPv4 / IPv6 双栈,UDP Socket 可根据需求配置为 UDP4、UDP6 或双栈模式。
硬件连接与拓扑
请注意:
测试需要 PC 端和 W6300 处于同一网段。PC 端需运行 UDP 测试程序。
Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
网线连接开发板 RJ45 网口 到路由器 LAN 口
确保 W6300 与 MH2457 之间的 QSPI 连线正确(CSn、SCK、DATA0~DATA3)
┌─────────────────────────────────┐
│ 路由器(DHCP Server) │
│ 192.168.1.1 │
└────┬──────────────────┬───────────┘
│ │
┌────┴──────┐ ┌────┴──────┐
│ W6300 │ │ PC │
│UDP Server │ │SocketTester│
│ IP: DHCP │ │UDP Client │
│port:5000 │ │ │
└────┬──────┘ └───────────┘
│ QSPI ↑
┌────┴──────┐ DEBUG USB
│ MH2457 │──────────→ WIZ UartTool
│ MCU │
└───────────┘
网络拓扑:W6300 作为 UDP 回环服务器,PC 端发送 UDP 数据并接收回环,MH2457 通过 QSPI 驱动 W6300
工程结构
工程核心文件如下:
Project/
├── main.c ← 系统入口:串口、GPIO、QSPI 初始化 + user_run()
└── USER/
├── user_main.c/h ← 网络地址定义 + user_run() 主流程
├── loopback/
│ ├── loopback.c ← loopback_udps() 状态机核心
│ └── loopback.h
├── wiz_platform.c/h ← 平台适配:debug_usart_init、wizchip_gpio_init、hspi_init
├── wiz_interface.c/h ← W6300 驱动接口:wizchip_initialize、network_init、PHY 检测
└── wizchip_conf.h ← WIZnet 配置与 wiz_NetInfo 定义
步骤1:主循环运行UDP回环测试
文件:USER/user_main.c
while (1)
{
loopback_udps(SOCKET_ID, ethernet_buf, local_port);
}
三个传参分别为:SOCKET ID、UDP 协议缓存数组、本地监听端口号。示例本地端口为 5000。主循环不断调用状态机函数,等待 UDP 数据报文到达并回环发送。
步骤2:UDP状态机
loopback_udps() 函数基于 getsockopt(sn, SO_STATUS, &status) 返回的 Socket 状态执行对应操作。UDP 模式状态简单,只有 SOCK_CLOSED 和 SOCK_UDP 两个状态:
Socket状态 执行操作
SOCK_CLOSED 打开 UDP Socket(按协议栈模式选择 UDP4/UDP6/UDPD),绑定端口,进入 SOCK_UDP
SOCK_UDP recvfrom() 接收数据并获取对端地址,sendto() 回环发送
文件:USER/loopback/loopback.c | 函数:loopback_udps()
int32_t loopback_udps(uint8_t sn, uint8_t* buf, uint16_t port)
{
check_loopback_mode_W6x00();
uint8_t status;
static uint8_t destip[16] = {0,};
static uint16_t destport;
uint8_t addr_len;
int32_t ret;
uint16_t received_size;
uint16_t sentsize;
uint8_t* mode_msg;
if (loopback_mode == AS_IPV4)
mode_msg = msg_v4;
else if (loopback_mode == AS_IPV6)
mode_msg = msg_v6;
else
mode_msg = msg_dual;
getsockopt(sn, SO_STATUS, &status);
switch (status)
{
case SOCK_UDP:
getsockopt(sn, SO_RECVBUF, &received_size);
if (received_size > DATA_BUF_SIZE)
received_size = DATA_BUF_SIZE;
if (received_size > 0)
{
ret = recvfrom(sn, buf, received_size, (uint8_t*)&destip, (uint16_t*)&destport, &addr_len);
if (ret <= 0) return ret;
received_size = (uint16_t)ret;
sentsize = 0;
while (sentsize != received_size)
{
ret = sendto(sn, buf + sentsize, received_size - sentsize, destip, destport, addr_len);
if (ret < 0) return ret;
sentsize += ret;
}
}
break;
case SOCK_CLOSED:
switch (loopback_mode)
{
case AS_IPV4: socket(sn, Sn_MR_UDP4, port, SOCK_IO_NONBLOCK); break;
case AS_IPV6: socket(sn, Sn_MR_UDP6, port, SOCK_IO_NONBLOCK); break;
case AS_IPDUAL: socket(sn, Sn_MR_UDPD, port, SOCK_IO_NONBLOCK); break;
}
printf("%d:Opened, UDP loopback, port [%d] as %s\r\n", sn, port, mode_msg);
break;
default:
break;
}
return 0;
}
状态机核心:SOCK_CLOSED 时按当前协议栈模式调用 socket(sn, Sn_MR_UDP4/6/D, port, SOCK_IO_NONBLOCK) 打开 UDP Socket 并绑定端口;SOCK_UDP 时调用 recvfrom() 接收数据并自动获取对端 IP 和端口,然后 sendto() 将数据回环发送给对端。UDP 无需建立连接,状态机比 TCP 简单得多。
recvfrom() / sendto() — UDP 收发 API
recvfrom(sn, buf, size, destip, &destport, &addr_len) 接收 UDP 数据报文,同时将发送方的 IP 地址、端口号以及地址长度(4 表示 IPv4,16 表示 IPv6)写入对应参数。sendto(sn, buf, size, destip, destport, addr_len) 向指定 IP 和端口发送 UDP 数据。这两个函数是 UDP 编程的核心——每次收发都携带对端地址,无需维护连接状态。
如果你想自定义
改监听端口 → 修改 user_main.c 中 local_port 的值
改用 IPv6 或双栈模式 → 调用 set_loopback_mode_W6x00(AS_IPV6) 或 AS_IPDUAL
主动发送 UDP 数据 → 在 SOCK_UDP 状态中直接调用 sendto(),指定目标 IP 和端口
支持广播 → 将目标 IP 设为 255.255.255.255 或子网广播地址
改用其他 Socket 编号 → 修改 SOCKET_ID 宏(W6300 支持 0-7 共 8 个 Socket)
运行验证
打开 WIZ UartTool V1.0 ,连接 DEBUG USB 对应 COM 口(115200 / 8N1),观察开发板串口输出。UDP Socket 打开后会打印监听提示:
MH2457 W6300 QSPI example start
W6300 UDP example
PHY link
The current Mbtis speed : 100Mbps
The current Duplex Mode : Full-Duplex
DHCP running
DHCP success!
====================================================================================================
W6300 network configuration : DHCP
MAC : 00:08:DC:12:34:56
IP : 192.168.1.8
Subnet Mask : 255.255.255.0
Gateway : 192.168.1.1
DNS : 192.168.1.1
====================================================================================================
1:Opened, UDP loopback, port [5000] as IPv4 mode
然后打开 SocketTester ,设置为 UDP 模式,输入 W6300 的 IP 地址(192.168.1.8)和端口号(5000),点击"Connect"。向 W6300 发送 UDP 数据,即可收到回环数据,验证 UDP 通信正常。
WIZ UartTool 串口输出 — UDP 回环初始化(PHY 链路 + DHCP + UDP Socket 打开)WIZ UartTool + SocketTester UDP 客户端 — 数据回环测试 常见问题
Q: UDP和TCP有什么区别
UDP 无连接、不可靠但高效,无需三次握手,头部仅 8 字节。TCP 面向连接、可靠传输,通过三次握手建立连接,头部 20 字节。UDP 适合实时音视频、DNS 查询等场景,TCP 适合文件传输、网页浏览等场景。
Q: UDP数据丢失怎么办
UDP 不保证数据可靠传输,丢包由应用层处理。常见方案:1) 应用层添加序号和 ACK 确认机制;2) 对丢失不敏感的场景(如音视频)直接忽略;3) 如需可靠性建议使用 TCP。W6300 硬件会自动丢弃校验错误的 UDP 报文。
Q: recvfrom和recv有什么区别
recvfrom() 用于 UDP,接收数据同时获取发送方 IP、端口和地址长度(通过 destip、destport 和 addr_len 参数)。recv() 用于 TCP,已建立连接无需获取对端地址。UDP 使用 recvfrom/sendto,TCP 使用 recv/send。
Q: UDP支持广播吗
支持。将 sendto() 的目标 IP 设为 255.255.255.255(全局广播)或子网广播地址(如 192.168.1.255),即可向网络中所有设备发送 UDP 广播报文。广播常用于设备发现、服务通告等场景。
总结
本文基于 W6300 硬件 TCP/IP 协议栈实现了 UDP 数据回环测试:
UDP 协议: 无连接、不可靠但高效,头部仅 8 字节,适合实时性要求高的场景
核心函数: loopback_udps() 基于 Socket 状态机,SOCK_CLOSED → SOCK_UDP 两状态切换
收发 API: recvfrom() 接收数据并获取对端地址,sendto() 向指定地址发送数据
双协议栈: W6300 支持 IPv4 / IPv6 / 双栈模式,通过 socket() 的 Sn_MR_UDP4/UDP6/UDPD 选择
无需连接: UDP 无需三次握手,Socket 打开后即可收发,状态机比 TCP 简单
支持广播: 将目标 IP 设为 255.255.255.255 即可发送 UDP 广播报文