全部例程

W6300 IPv4 IPv6 双栈 TCP客户端与服务器

W6300

更新于 2026年10月16日

本篇总结

使用 W6300 的硬件 TOE 引擎,在 IPv4/IPv6 双协议栈下同时运行 4 路 TCP(IPv4 服务器/客户端 + IPv6 服务器/客户端),先通过 DHCP 获取 IPv4 地址、SLAAC 获取 IPv6 地址,再并行进行数据回环测试。

🔑 MH2457、QSPI、UART 调试、硬件 TOE 引擎、IPv4、IPv6、SLAAC、双协议栈、TCP

硬件平台:本例程基于 W6300-EVB-M4 开发板运行。

采购推荐:点击前往 WIZnet 官方淘宝店铺 选购 W6300-EVB-M4 开发板

本示例演示使用 W6300 的硬件 TOE 引擎,在 IPv4/IPv6 双协议栈下同时运行 4 路 TCP 通信。W6300 原生支持 IPv4/IPv6 双协议栈,本例程先通过 DHCP 获取 IPv4 地址,再通过 DAD 检测生成 Link-local 地址、通过路由器公告(RA)进行无状态地址自动配置(SLAAC)获取 IPv6 Global 地址,最后在主循环中并行运行 IPv4 服务器(监听 5000)、IPv4 客户端、IPv6 服务器(监听 6000)和 IPv6 客户端。

前置工具准备

开始本例程前,请确认以下工具已安装:

IPv4 / IPv6 双栈 TCP 通信简介

W6300 片内集成完整的硬件双协议栈 TCP/IP,支持 IPv4、IPv6 以及双栈模式,Socket 可通过 Sn_MR_TCP4、Sn_MR_TCP6、Sn_MR_TCPD 选择协议栈模式。本例程使用 8 个独立 Socket 中的 4 个,分别运行 IPv4 服务器、IPv4 客户端、IPv6 服务器和 IPv6 客户端。

地址获取方式:

  • IPv4 地址:通过 DHCP 从路由器获取(本例为 192.168.1.8)。
  • IPv6 Link-local 地址:根据 MAC 地址自动生成(FE80::/10 前缀),通过 DAD 检测确认唯一。
  • IPv6 Global 地址:通过路由器公告(RA)进行 SLAAC 无状态地址自动配置,必要时通过 Stateless DHCPv6 获取 DNS。

双栈并行运行

W6300 的 TOE 引擎支持 8 个独立 Socket,可同时运行 IPv4 和 IPv6 通信。本例程使用 4 个 Socket:Socket 1 和 3 分别作为 IPv4/IPv6 服务器监听固定端口,Socket 2 和 4 分别作为 IPv4/IPv6 客户端主动连接远端服务器。四路在主循环中交替调用,互不干扰。

硬件连接与拓扑

请注意:

测试需要路由器支持并开启 IPv6,且发送 RA 公告。PC 和开发板需在同一网段。PC 端同时作为 IPv4/IPv6 客户端和服务器与开发板通信。

  1. Micro USB 线连接 DEBUG USB 口到 PC(供电 + 调试串口)
  2. 网线连接开发板 RJ45 网口 到路由器 LAN 口
┌─────────────────────────────────┐
│ 路由器(DHCP / IPv6 RA) │
│ 192.168.1.1 │
└────┬──────────────────┬───────────┘
│ │
┌────┴──────┐ ┌────┴──────┐
│ W6300 │ │ PC │
│ TCP Srv x2│ │SocketTester│
│ TCP Clt x2│ │TCP Clt/Srv│
│ IPv4+IPv6 │ │ IPv4+IPv6 │
└────┬──────┘ └───────────┘
│ QSPI ↑
┌────┴──────┐ DEBUG USB
│ MH2457 │─────────→ WIZ UartTool
│ MCU │
└───────────┘
网络拓扑:MH2457 通过 QSPI 驱动 W6300,W6300 在 IPv4/IPv6 双栈下同时运行 2 路服务器 + 2 路客户端

工程结构

工程核心文件如下:

Project/
├── main.c                    ← 系统入口:串口、GPIO、QSPI 初始化 + user_run()
└── USER/
    ├── user_main.c           ← IPv4/IPv6 配置 + 四路 TCP 主循环
    ├── ipv6_aac.c/h          ← IPv6 无状态地址自动配置(SLAAC)
    ├── ipv6_common.c/h       ← IPv6 地址准备与打印
    ├── loopback_compat.c/h   ← IPv4/IPv6 TCP 服务器/客户端封装(重连退避)
    ├── loopback.c/h          ← loopback_tcps() / loopback_tcpc() 状态机核心
    ├── wiz_platform.c/h      ← 平台适配:debug_usart_init、wizchip_gpio_init、hspi_init
    └── wiz_interface.c/h     ← W6300 驱动接口:wizchip_initialize、network_init、PHY 检测、软件定时器

步骤1:IPv4/IPv6 地址配置

文件:USER/user_main.c — 先通过 network_init() 获取 IPv4 地址,再调用 ipv6_aac_configure() 执行 DAD 检测和 RA 解析,完成 IPv6 地址自动配置。

wizchip_initialize();
network_init(ethernet_buf, &default_net_info);

if (ipv6_aac_configure(default_net_info.mac) < 0)
{
    printf("IPv6 auto configuration failed; dual-stack application loop is not started\r\n");
    return;
}
printf("IPv4/IPv6 configuration complete; starting dual-stack application loop\r\n");

软件定时器

W6300 的 DHCPv6 时基通过 wiz_add_timer(DHCP6_time_handler, 1000) 注册到软件定时器链表,由 1ms 中断调用 wiz_timer_handler() 驱动。地址自动配置完成后调用 wiz_delete_timer() 删除定时器。

步骤2:主循环并行运行四路 TCP

文件:USER/user_main.c — 先通过 network_init() 获取 IPv4 地址,再调用 ipv6_aac_configure() 执行 DAD 检测和 RA 解析,完成 IPv6 地址自动配置。

wizchip_initialize();
network_init(ethernet_buf, &default_net_info);

if (ipv6_aac_configure(default_net_info.mac) < 0)
{
    printf("IPv6 auto configuration failed; dual-stack application loop is not started\r\n");
    return;
}
printf("IPv4/IPv6 configuration complete; starting dual-stack application loop\r\n");

软件定时器

W6300 的 DHCPv6 时基通过 wiz_add_timer(DHCP6_time_handler, 1000) 注册到软件定时器链表,由 1ms 中断调用 wiz_timer_handler() 驱动。地址自动配置完成后调用 wiz_delete_timer() 删除定时器。

步骤3:TCP 服务器/客户端状态机

文件:USER/loopback_compat.c — ipv4_tcp_server_run() / ipv6_tcp_server_run() 设置协议栈模式后调用底层 loopback_tcps() 状态机;ipv4_tcp_client_run() / ipv6_tcp_client_run() 带重连退避调用 loopback_tcpc()。

int32_t ipv4_tcp_server_run(uint8_t sn, uint8_t *buf, uint16_t port)
{
    if (set_loopback_mode_W6x00(AS_IPV4) != 0)
    {
        return -1;
    }
    return loopback_tcps(sn, buf, port);
}

int32_t ipv6_tcp_server_run(uint8_t sn, uint8_t *buf, uint16_t port)
{
    if (set_loopback_mode_W6x00(AS_IPV6) != 0)
    {
        return -1;
    }
    return loopback_tcps(sn, buf, port);
}

int32_t ipv4_tcp_client_run(uint8_t sn, uint8_t *buf, uint8_t *dest_ip, uint16_t dest_port)
{
    return tcp_client_run_with_retry(sn, buf, dest_ip, dest_port, AS_IPV4);
}

int32_t ipv6_tcp_client_run(uint8_t sn, uint8_t *buf, uint8_t *dest_ip6, uint16_t dest_port)
{
    return tcp_client_run_with_retry(sn, buf, dest_ip6, dest_port, AS_IPV6);
}

重连退避机制

TCP 客户端连接失败时,tcp_client_schedule_retry() 记录下次重试时间,tcp_client_retry_ready() 在重试时间到达前返回 SOCK_BUSY,避免主循环被连接阻塞,也避免过于频繁地重试打印。四路 TCP 共享一个主循环,这一点尤为重要。

运行验证

打开 WIZ UartTool V1.0,连接 DEBUG USB 对应 COM 口(115200 / 8N1)。烧录例程运行后,首先获取 IPv4 地址,然后执行 DAD 检测和 RA 解析,完成 IPv6 地址自动配置,最后启动四路 TCP。预期串口输出如下:

MH2457 W6300 QSPI example start
W6300 IPv4 / IPv6 Dual Stack TCP Client / Server 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
====================================================================================================

Duplicate_Address_Detection
Wait RQIR.....

Timeout !!! DAD SUCCESSED

flags = 0x80
Address_Auto_Configuration Start
RA capture mode : W6300 MACRAW
Sn_SR : 42
RA
type : 86
code : 0
RA_flag : 58
Router_lifetime : 1800 s
Reachable_time : 0 ms
Retrans_time : 0 ms
Option Type : 3, length : 32
Prefix Length : 64
Prefix Information Flag : c0
valid lifetime : 259200
preferred lifetime : 172800
Accepted first autonomous /64 PIO
Option Type : 24, length : 24
Option Type : 25, length : 24
DNS lifetime : 1200
Option Type : 1, length : 8
MO normalized result : 1
RA requests Stateless DHCPv6
Mac address : 00:08:dc:12:34:56
your Link Local IP is fe80:0000:0000:0000:0208:dcff:fe12:3456
your Global IP is 240e:033d:9473:c700:0208:dcff:fe12:3456
your Gateway IP is fe80:0000:0000:0000:e2f6:78ff:fe66:eed0
your DNSv6 is fe80:0000:0000:0000:0000:0000:0000:0001
Stateless DHCPv6 succeeded
Link-local address: FE80:0000:0000:0000:0208:DCFF:FE12:3456
Global address: 240E:033D:9473:C700:0208:DCFF:FE12:3456
IPv6 gateway: FE80:0000:0000:0000:E2F6:78FF:FE66:EED0
IPv6 DNS: FE80:0000:0000:0000:0000:0000:0000:0001
IPv4/IPv6 configuration complete; starting dual-stack application loop
1:TCP server loopback start
1:Socket opened[19]
3:TCP server loopback start
3:Socket opened[19]
1:Listen, TCP server loopback, port [5000] as IPv4 mode
2:Try to connect to the 192.168.1.12, 5001
3:Listen, TCP server loopback, port [6000] as IPv6 mode
4:Try to connect to the 240E:033D:9473:C700:5324:E448:7FF6:F17E,6001

串口输出依次显示 IPv4 DHCP 成功、DAD 检测成功、RA 报文解析、IPv6 地址自动配置完成,最后四路 TCP 全部启动:Socket 1 作为 IPv4 服务器监听 5000,Socket 3 作为 IPv6 服务器监听 6000,Socket 2 作为 IPv4 客户端连接 192.168.1.12:5001,Socket 4 作为 IPv6 客户端连接 240E:033D:9473:C700:5324:E448:7FF6:F17E:6001。

四路 TCP 的测试方法如下:

角色Socket协议端口对端
IPv4 服务器1TCP5000PC 作为 TCP Client 连接 W6300 192.168.1.8:5000
IPv4 客户端2TCP本地任意W6300 连接 PC 192.168.1.12:5001
IPv6 服务器3TCP6000PC 作为 TCP Client 连接 W6300 IPv6 240E:033D:9473:C700:0208:DCFF:FE12:3456:6000
IPv6 客户端4TCP本地任意W6300 连接 PC IPv6 240E:033D:9473:C700:5324:E448:7FF6:F17E:6001
WIZ UartTool 串口输出 — W6300 作为 IPv4 服务器(5000)通信
ketTester — IPv4 TCP 客户端通信WIZ UartTool 串口输出 — W6300 作为 IPv4 客户端连接 PC(5001)通信
WIZ UartTool 串口输出 — W6300 作为 IPv6 服务器(6000)通信
WIZ UartTool 串口输出 — W6300 作为 IPv6 客户端连接 PC(6001)通信

常见问题

Q: 为什么 IPv4 和 IPv6 要分开获取地址

IPv4 通过 DHCP 从路由器获取地址,IPv6 通过 SLAAC(无状态地址自动配置)从路由器公告(RA)中获取前缀并生成地址。两种协议的地址分配机制不同,所以需要分别配置。W6300 支持双栈,可以同时运行两种协议。

Q: 为什么 IPv6 要先做 DAD 检测

IPv6 设备在链路上通信前必须先拥有一个唯一的 Link-local 地址。DAD(重复地址检测)通过发送邻居请求确认该地址没有被其他设备占用,确保地址唯一后才能继续获取 Global 地址。串口打印 "DAD SUCCESSED" 表示地址可用。

Q: 四路 TCP 可以同时运行吗

可以。W6300 的 TOE 引擎支持 8 个独立 Socket,四路 TCP 各使用一个 Socket,在主循环中交替调用各自的运行函数即可并行工作。服务器 Socket 监听固定端口,客户端 Socket 主动连接远端服务器,互不干扰。

Q: 为什么 TCP 客户端连接失败后要退避重试

TCP 客户端在服务器未开启时会反复连接失败。如果每次失败都立即重试,会在主循环中产生大量重试和串口打印,影响其他三路 TCP 的运行。通过 tcp_client_schedule_retry() 记录下次重试时间,在重试时间到达前返回 SOCK_BUSY,既能继续轮询连接进度,又不会阻塞主循环。

Q: IPv6 地址自动配置失败怎么办

排查步骤:1) 确认路由器支持并开启 IPv6,且发送 RA 公告;2) 确认 PC 和 W6300 在同一网段;3) 检查串口是否打印 DAD SUCCESSED 和 RA 解析信息;4) 若 RA 未收到,检查路由器 IPv6 配置和光猫是否将 IPv6 前缀委派给路由器;5) 程序在自动配置失败时不会启动应用循环,可根据串口提示定位问题。

总结

Q: 为什么 IPv4 和 IPv6 要分开获取地址

IPv4 通过 DHCP 从路由器获取地址,IPv6 通过 SLAAC(无状态地址自动配置)从路由器公告(RA)中获取前缀并生成地址。两种协议的地址分配机制不同,所以需要分别配置。W6300 支持双栈,可以同时运行两种协议。

Q: 为什么 IPv6 要先做 DAD 检测

IPv6 设备在链路上通信前必须先拥有一个唯一的 Link-local 地址。DAD(重复地址检测)通过发送邻居请求确认该地址没有被其他设备占用,确保地址唯一后才能继续获取 Global 地址。串口打印 "DAD SUCCESSED" 表示地址可用。

Q: 四路 TCP 可以同时运行吗

可以。W6300 的 TOE 引擎支持 8 个独立 Socket,四路 TCP 各使用一个 Socket,在主循环中交替调用各自的运行函数即可并行工作。服务器 Socket 监听固定端口,客户端 Socket 主动连接远端服务器,互不干扰。

Q: 为什么 TCP 客户端连接失败后要退避重试

TCP 客户端在服务器未开启时会反复连接失败。如果每次失败都立即重试,会在主循环中产生大量重试和串口打印,影响其他三路 TCP 的运行。通过 tcp_client_schedule_retry() 记录下次重试时间,在重试时间到达前返回 SOCK_BUSY,既能继续轮询连接进度,又不会阻塞主循环。

Q: IPv6 地址自动配置失败怎么办

排查步骤:1) 确认路由器支持并开启 IPv6,且发送 RA 公告;2) 确认 PC 和 W6300 在同一网段;3) 检查串口是否打印 DAD SUCCESSED 和 RA 解析信息;4) 若 RA 未收到,检查路由器 IPv6 配置和光猫是否将 IPv6 前缀委派给路由器;5) 程序在自动配置失败时不会启动应用循环,可根据串口提示定位问题。

下载本章例程

我们提供完整的工程文件以及配套开发板,方便你随时测试,快速完成产品开发:

开发环境: Keil MDK5

Andy

W5500 技术支持专家