单网卡绑定多个 IP 地址
参数:
网卡物理单网卡
掩码 255.255.0.0 → 网段:192.9.0.0/16
需要两个本地 IP:
IP1:192.9.2.100
IP2:192.9.10.1
情景:
我的软件需要两个ip的udp套接字
一个是192.9.2.100
一个是192.9.10.1
但子网掩码是255.255.0.0
但我的电脑是单网卡
关键点:两个 IP属于同一个大网段 192.9.0.0/16!
不存在跨网关、路由冲突问题!
不需要虚拟网卡、不需要 USB 网卡、不需要 VLAN。
最优解决方案:单网卡绑定多个 IP 地址(本机多 IP)
操作系统原生支持,零额外软件,Qt UDP Socket 完全兼容。
你在代码里创建两个 UDP 套接字,分别绑定两个本地 IP 即可:
QUdpSocket sock1, sock2;
sock1.bind(QHostAddress("192.9.2.100"), 端口);
sock2.bind(QHostAddress("192.9.10.1"), 端口);
Windows 配置步骤
- 网卡 → IPv4 属性 →【高级】
- IP 地址区域点击【添加】
- 地址:
192.9.2.100掩码:255.255.0.0 - 再点添加:
192.9.10.1掩码:255.255.0.0
- 地址:
- 网关只填写一个(不要填多个网关!同网段多网关会出诡异路由问题)
cmd 查看是否生效:
ipconfig,网卡会列出两个 IPv4 地址
银河麒麟(Linux ARM)配置方案(两种任选)
方式 1:nmcli 命令(NetworkManager,图形系统推荐)
NetworkManagerClient
# 假设网卡名称 eth0,替换成你的网卡名(ip a查看)
nmcli connection modify eth0 ipv4.addresses "192.9.2.100/16,192.9.10.1/16"
nmcli connection modify eth0 ipv4.method manual
# 网关只设置一个,示例网关按需修改
nmcli connection modify eth0 ipv4.gateway "192.9.0.1"
nmcli connection up eth0
方式 2:ifupdown / 静态配置文件(无桌面服务器)
在 interfaces 配置额外地址(secondary 地址)
auto eth0
iface eth0 inet static
address 192.9.2.100
netmask 255.255.0.0
gateway 192.9.0.1
iface eth0 inet static
address 192.9.10.1
netmask 255.255.0.0
重启网络生效。
验证:ip a 看到网卡上两个 inet 地址。
非常重要的坑(针对 UDP 通信)
- 同网卡多个 IP,收发 UDP 完全正常,socket 绑定指定 IP 可以区分源地址;
- 远端回复报文能不能正确送达,同 / 16 网段完全没问题,二层可达;
- ❌不要两个 IP 配置两个网关!同一个 / 16 网段只保留一条默认网关;
- 注意防火墙:两个 IP 的端口都要放行;
- Qt UDP 注意:不要 bind (0.0.0.0),必须显式绑定指定 IP,否则系统随机选用源 IP,无法区分两套链路。
补充:会不会出现什么异常?
很多人担心:单网卡两个 IP,会不会收到的包分不清属于哪个 socket?不会。当你 bind(指定IP) 之后:
- 目标 IP=192.9.2.100 的报文 → 进入 sock1
- 目标 IP=192.9.10.1 的报文 → 进入 sock2
- Linux/Windows 协议栈原生区分,工业 UDP 场景大量这么用。
什么时候才需要虚拟网卡 / USB 网卡?
只有下面场景才需要额外硬件 / 虚拟网卡:
两个 IP 属于不同主网段(比如一个 192.9.x.x,一个 10.0.x.x,且需要两套独立网关);
你当前场景完全不需要!
我的套接字使用的是原生c代码 不是qt
原生 C socket 完全支持。
关键点:创建两个 socket,调用bind()显式绑定各自本地 IP,不能绑定INADDR_ANY。
C 原生 UDP 最简示例(Linux/Windows 通用思路,区分平台头文件)
Linux (银河麒麟 ARM)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 8080
int main()
{
int fd1, fd2;
struct sockaddr_in addr_local1, addr_local2;
// socket1 绑定 192.9.2.100
fd1 = socket(AF_INET, SOCK_DGRAM, 0);
memset(&addr_local1, 0, sizeof(addr_local1));
addr_local1.sin_family = AF_INET;
addr_local1.sin_port = htons(PORT);
inet_pton(AF_INET, "192.9.2.100", &addr_local1.sin_addr);
if (bind(fd1, (struct sockaddr *)&addr_local1, sizeof(addr_local1)) < 0)
{
perror("bind 192.9.2.100 failed");
return -1;
}
// socket2 绑定 192.9.10.1
fd2 = socket(AF_INET, SOCK_DGRAM, 0);
memset(&addr_local2, 0, sizeof(addr_local2));
addr_local2.sin_family = AF_INET;
addr_local2.sin_port = htons(PORT);
inet_pton(AF_INET, "192.9.10.1", &addr_local2.sin_addr);
if (bind(fd2, (struct sockaddr *)&addr_local2, sizeof(addr_local2)) < 0)
{
perror("bind 192.9.10.1 failed");
close(fd1);
return -1;
}
printf("两个UDP socket绑定成功\n");
printf("sock1: 192.9.2.100:%d\n", PORT);
printf("sock2: 192.9.10.1:%d\n", PORT);
// 后续可以用select/poll/epoll同时监听两个fd收发数据
close(fd1);
close(fd2);
return 0;
}
必须重视的几个底层坑(C 开发极易踩)
不要绑定 INADDR_ANY (0.0.0.0)
如果 bind 0.0.0.0,发送 UDP 时系统会自动选源 IP,你无法控制使用 192.9.2.100 还是 192.9.10.1;
✅强制:每个 socket 绑定独立本地 IP。
端口能否相同?
Linux:允许,不同本地 IP,相同端口可以 bind 成功(上面代码就是同端口)
Windows:默认情况下,同端口、不同 IP 也支持;极少数老旧系统需要开启SO_REUSEADDR
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐



所有评论(0)