我正在 Linux 中为相机 Controller 构建一个嵌入式系统(非实时)。我在让网络做我想做的事情时遇到问题。该系统有 3 个网卡、1 个 100base-T 和 2 个千兆端口。我将较慢的连接到相机(这是它所支持的全部),而较快的连接到其他机器的点对点连接。我正在尝试做的是从相机获取图像,进行一些处理,然后使用 UDP 将其广播到其他每个 NIC。
这是我的网络配置:
eth0: addr: 192.168.1.200 Bcast 192.168.1.255 Mask: 255.255.255.0 (这是100base-t)
eth1: 地址:192.168.2.100 Bcast 192.168.2.255 掩码:255.255.255.0
eth2: 地址:192.168.3.100 Bcast 192.168.3.255 掩码:255.255.255.0
图像以专有协议(protocol)从 eth0 进入,因此它是原始套接字。我可以将它广播到 eth1 或 eth2 就好了。但是当我尝试将它一个接一个地广播给两者时,我在 eth0 上遇到了很多网络问题和错误。
我像这样初始化 UDP 套接字:
sock2=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP); // Or sock3
sa.sin_family=AF_INET;
sa.sin_port=htons(8000);
inet_aton("192.168.2.255",&sa.sin_addr); // Or 192.168.3.255
setsockopt(sock2, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof(broadcast));
bind(sock2,(sockaddr*)&sa,sizeof(sa));
sendto(sock2,&data,sizeof(data),0,(sockaddr*)&sa,sizeof(sa)); // sizeof(data)<1100 bytes
我分别为每个套接字执行此操作,并分别调用 sendto。当我做一个或另一个时,没关系。当我尝试同时发送时,eth0 开始收到错误的数据包。
关于为什么会发生这种情况的任何想法?是不是配置错误,有没有更好的办法?
编辑: 感谢所有帮助,我一直在尝试一些事情并对此进行更多研究。严格来说,这个问题似乎不是广播问题。我用单播命令替换了广播代码,它具有相同的行为。我想我更好地理解了这种行为,但不知道如何解决它。
这是正在发生的事情。在 eth0 上,我应该每 50 毫秒获取一个图像。当我在 eth1(或 2)上发送图像时,发送图像大约需要 1.5 毫秒。当我尝试同时发送 eth1 和 eth2 时,大约需要 45 毫秒,偶尔会跳到 90 毫秒。当这超过 50 毫秒窗口时,eth0 的缓冲区开始构建。当然,当缓冲区变满时我会丢失数据包。
所以我修改了问题。为什么仅从一个以太网端口变为两个以太网端口,它就会从 1.5 毫秒变为 45 毫秒?
这是我的初始化代码:
sock[i]=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
sa[i].sin_family=AF_INET;
sa[i].sin_port=htons(8000);
inet_aton(ip,&sa[i].sin_addr);
//If Broadcasting
char buffer[]="eth1" // or eth2
setsockopt(sock[i],SOL_SOCKET,SO_BINDTODEVICE,buffer,5);
int b=1;
setsockopt(sock[i],SOL_SOCKET,SO_BROADCAST,&b,sizeof(b));
这是我的发送代码:
for(i=0;i<65;i++) {
sendto(sock[0],&data[i],sizeof(data),0,sa[0],sizeof(sa[0]));
sendto(sock[1],&data[i],sizeof(data),0,sa[1],sizeof(sa[1]));
}
这是非常基础的。
有什么想法吗?感谢您的大力帮助!
保罗
最佳答案
也许您的 UDP 堆栈内存不足?
(1) 检查/proc/sys/net/ipv4/udp_mem
(详见man 7 udp
)。确保第一个数字至少是图像大小的 8 倍。这将设置系统中所有 UDP 套接字的内存。
(2) 确保用于发送套接字的每个套接字缓冲区足够大。使用 setsockopt(sock2, SOL_SOCKET, SO_SNDBUF, image_size*2)
在两个套接字上设置发送缓冲区。您可能需要增加 /proc/sys/net/core/wmem_max
中允许的最大值。有关详细信息,请参见 man 7 socket
。
(3) 还不如增加接收socket的RX buffer。向.../rmem_max
写入一个大数,然后使用SO_RCVBUF
增加接收缓冲区大小。
关于c - 使用多个 NIC 广播 UDP 数据包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8112109/