我仍在实践linux的网络编程,如果您觉得它含糊不清或不正确,请随时澄清我的理解。
查询:
我已经用yocto项目烘焙了一个Linux映像,它类似于core image minimal。这部分与查询无关。我使用QEMU模拟器启动这个映像,当QEMU启动时,它会创建一个名为tap0的sudo接口。QEMU的IP是192.168.7.2,tap0的IP是192.168.7.1。
现在我有了另一个用简单C编写的用户空间程序,它试图监听QEMU程序(节点)发送的任何内容。所以,我用了一个类似的片段:

if ( (fd = open("/dev/net/tun",O_RDWR)) < 0) PERROR("open");

memset(&ifr, 0, sizeof(ifr));
ifr.ifr_flags = TUNMODE;
strncpy(ifr.ifr_name, "w-tap%d", IFNAMSIZ);
if (ioctl(fd, TUNSETIFF, (void *)&ifr) < 0) PERROR("ioctl");

printf("Allocated interface %s. Configure and use it\n", ifr.ifr_name);

s = socket(PF_INET, SOCK_DGRAM, 0);
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = htonl(INADDR_ANY);
sin.sin_port = htons(PORT);
if ( bind(s,(struct sockaddr *)&sin, sizeof(sin)) < 0) PERROR("bind");

fromlen = sizeof(from);
while(1) {
    l = recvfrom(s, buf, sizeof(buf), 0, (struct sockaddr *)&from, &fromlen);
    //print the data etc
}

现在,如果我用saysudo ./tun_proxy 1534启动这个C代码,我就能够监听这个端口上由192.168.7.2发送的消息。
此外,
我用附加选项启动QEMU-net socket,mcast=224.244.224.245:30490,因为baked image中有一个小程序,可以在多播组和端口上以广播的形式发送一些消息。另外,我应该能够在上一个tun_代理应用程序上监听这些消息。我甚至在其中创建了一个新线程,该线程尝试侦听多播组,但得到的错误消息是“已在使用中”
我的理解到底错在哪里?我只需要两个用户空间程序,其中一个是QEMU来通过多播消息进行通信。

最佳答案

你的理解是正确的,你只需要解决两个问题:
如果绑定到INADDR_ANY上,则会阻塞所有其他地址(包括多播)的端口,除非使用REUSEADDR。绑定的套接字也将接收到它阻止访问的多播,除了:
“主机”上的某些套接字需要使用INADDR_ANY,其中成员资格请求在任何套接字接收多播通信之前与通信量匹配。
模拟当前示例:
作为一个相当但相当奇怪的例子,IP_ADD_MEMBERSHIP相当于您的侦听器,并且shell1显示看似不相关的套接字的ip add membership(但对于正确的地址和所有接口)导致它接收通信量:

shell1$ socat UDP-RECVFROM:30490,bind=0.0.0.0 EXEC:date

shell2$ echo hi | socat UDP-DATAGRAM:224.244.224.245:30490 STDIO
shell1$ (socat is still waiting for a packet)

shell2-add-membership$ socat UDP-RECVFROM:1044,reuseaddr,bind=127.0.0.1,ip-add-membership=224.244.224.245:0.0.0.0 EXEC:date&
       [1] 16003
shell2$ echo hi | socat UDP-DATAGRAM:224.244.224.245:30490 STDIO
       Thu Sep  1 00:16:28 CEST 2016
shell1$ (socat now exits cleanly)

将其固定为多播:
因此,要运行2+客户端,正确的方法是:
shellclient1$ socat UDP-RECVFROM:30490,bind=0.0.0.0,reuseaddr,ip-add-membership=224.244.224.245:0.0.0.0 EXEC:date
shellclient2$ socat UDP-RECVFROM:30490,bind=0.0.0.0,reuseaddr EXEC:date
...
shellclientn$ socat UDP-RECVFROM:30490,bind=0.0.0.0,reuseaddr EXEC:date


shell2$ echo hi | socat UDP-DATAGRAM:224.244.224.245:30490 STDIO
       Thu Sep  1 00:16:28 CEST 2016
       ...

请注意,所有成员都必须使用sou REUSEADDR,但只有一个成员必须添加成员身份。
Qemu's socket network uses shell2并成为会员。因此,阻塞套接字的代码可能是其他需要修改以类似Qemu的代码。

关于c - 通过多播在Tun上使用2个用户空间程序,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39186913/

10-12 21:26