使用多个NIC广播UDP数据包

时间:2011-11-13 14:09:33

标签: c linux network-programming udp broadcast

我正在为Linux中的摄像机控制器构建一个嵌入式系统(非实时)。我在网络上做我想做的事情时遇到了问题。该系统有3个NIC,1个100base-T和2个千兆端口。我将较慢的一个连接到摄像机(这是所有它支持的),而较快的是与其他机器的点对点连接。我试图做的是从相机中获取图像,进行一些处理,然后使用UDP将其广播到其他每个NIC。

这是我的网络配置:

eth0:addr:192.168.1.200 Bcast 192.168.1.255掩码:255.255.255.0(这是100base-t)
eth1:addr:192.168.2.100 Bcast 192.168.2.255掩码:255.255.255.0
eth2:addr:192.168.3.100 Bcast 192.168.3.255掩码:255.255.255.0

图像通过专有协议进入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上我应该每50ms获得一个图像。当我在eth1(或2)上发送图像时,发送图像大约需要1.5ms。当我尝试同时发送eth1和eth2时,大约需要45ms,偶尔会跳到90ms。当这超出50ms窗口时,eth0的缓冲区开始构建。当然,当缓冲区满了时,我会丢失数据包。

所以我修改过的问题。为什么从一个以太网端口转到两个端口,从1.5ms到45ms呢?

这是我的初始化代码:

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]));
}

这很基本。

有什么想法吗?感谢您的大力帮助!

3 个答案:

答案 0 :(得分: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中增加maximumu允许值。有关详细信息,请参阅man 7 socket

(3)你也可以增加接收套接字的RX缓冲区。将一个大数字写入.../rmem_max,然后使用SO_RCVBUF增加接收缓冲区大小。

答案 1 :(得分:1)

在实际解决此问题之前的解决方法可能是为eth1 + eth2创建桥接并将数据包发送到该网桥。 因此,它只映射到内核内存一次,而不是每个映像两次。

答案 2 :(得分:0)

已经很长时间了,但是我找到了问题的答案,所以我想我会把它放在这里以防其他人找到它。

两个千兆以太网端口实际上位于PCI-express总线的PCI桥上。 PCI-express总线是主板的内部,但它是PCI总线。桥和总线没有足够的带宽来实际快速发送图像。只启用了一个网卡,数据就会被发送到缓冲区,对我而言看起来非常快,但实际通过总线,出卡和接线都需要更长的时间。第二个NIC速度较慢,因为缓冲区已满。虽然更改缓冲区大小会掩盖问题,但它实际上并没有更快地发送数据,而且我仍然在第三个NIC上丢弃数据包。

最后,100Base-T卡实际上是内置在主板上的,因此有一个更快的总线,导致总体上比千兆端口更快的带宽。通过将相机切换到千兆线和其中一个到100Base-T线的千兆线我能够满足要求。

奇怪。