c - 使用多个 NIC 广播 UDP 数据包

标签 c linux network-programming udp broadcast

我正在 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/

相关文章:

c - C 的这种行为是如何解释的?

c - 在 C 中减去两个指针时

linux - 找不到 Mozilla 运行时

linux - 阻止 RHEL 上所有可能的子域的所有流量?

c++ - 基于 libpcap 的应用程序是否会影响网络速度/性能?

c - LWIP ECHO SERVER:如何增加itoa函数中的缓冲区大小?

c - 是否可以在 C 中合并 stderr 和 stdout?

linux - 如何将输入/输出连接到 SSH session

c++ - 我怎样才能在任何随机时间退出选择的系统调用?

c - C 中的 Telnet 服务器和客户端代码