使用多个NIC广播UDP数据包

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

这是我的networkingconfiguration:

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 Mask:255.255.255.0

该图像是在专有协议eth0中来的,所以它是一个原始的套接字。 我可以把它播放到eth1或eth2就好了。 但是,当我尝试将它广播到两个,一个接一个,我得到了很多networking打嗝和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开始收到错误的数据包。

任何想法,为什么发生这种情况? 这是一个configuration错误,有没有更好的方法来做到这一点?

编辑:感谢所有的帮助,我一直在尝试一些东西,并进一步调查。 严格来说,这个问题似乎并不是广播。 我用单播命令replace广播代码,它具有相同的行为。 我想我更好地理解行为,但不是如何解决这个问题。

这是发生了什么事。 在eth0上,我应该每50ms获得一张图片。 当我在eth1(或2)上发送图像时,发送图像大约需要1.5ms。 当我同时发送eth1和eth2时,大约需要45ms,偶尔跳到90ms。 当这超出了50ms窗口,eth0的缓冲区开始build立。 当然,当缓冲区满了,我会丢失数据包。

所以我修改的问题。 为什么从一个以太网端口转到两个,从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])); } 

这是非常基本的。

有任何想法吗? 感谢您的帮助!

保罗

也许你的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)你也可以增加RX缓冲区来接收socket。 写一个大的数字到.../rmem_max ,然后使用SO_RCVBUF来增加接收缓冲区大小。

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

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

两个千兆位以太网端口实际上位于PCI高速总线的PCI桥上。 PCI高速总线是在主板内部,但它是一个PCI总线去卡。 桥和公共汽车没有足够的带宽来实际发送快速的图像。 只有一个网卡启用的数据被发送到缓冲区,它看起来非常快,但实际上通过总线,卡,然后到电线花了更长的时间。 第二块网卡比较慢,因为缓冲区已满。 尽管更改缓冲区大小掩盖了问题,但实际上并没有更快地发送数据,而且我仍然在第三个NIC上丢弃数据包。

最后,100Base-T卡实际上是内置在主板上,因此总线速度更快,因此带宽总体上比千兆端口更快。通过将摄像头切换到千兆线路和千兆线路之一100Base-T线我能够满足要求。

奇怪。