UDP IPv6连接在选择多播默认接口时失败
问题描述
我目前正在尝试使用多播设置IPv6客户端/服务器UDP通信。
连接 +发送
我面临的问题在Connect
call for IPv6 udp Multicast套接字:
- (a)如果我选择默认接口
0
使用SetSockopt
和ipv6_multicast_if
连接调用将失败。 - (b)如果我选择与系统中一个实际活动的多播接口相对应的接口索引(例如
f_nametoindex(“ eth0”)
),则它将成功。
使用sendto
没有先验连接
的sendto
,在两种情况下,默认接口 0 (a)将在两种情况下成功使用。 或通过IF_NAMETOINDEX
(b)的相应接口。
示例
该示例显示运行客户端以发送到多播地址的四个可能性。编译和运行:
- 连接 +发送(a):
./ main 1
- 失败:无效参数 - 连接 + send(b):
./ main 1 eth0
- 成功 - sendto (a):
./ main 0
- 成功 - sendto(b):
./ main 0 eth0
- 成功
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define MAXBUF 65536
#define ADDR "ff02::1:5"
#define PORT "50000"
int client(int use_connect_and_send, int interface_index) {
int sock;
int status;
struct addrinfo sainfo, *psinfo, *linfo;
struct sockaddr_in6 sin6;
int sin6len;
char buffer[MAXBUF];
sprintf(buffer, "hello");
sin6len = sizeof(struct sockaddr_in6);
sock = socket(AF_INET6, SOCK_DGRAM, 0);
memset(&sin6, 0, sizeof(struct sockaddr_in6));
sin6.sin6_port = htons(0);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = in6addr_any;
memset(&sainfo, 0, sizeof(struct addrinfo));
memset(&sin6, 0, sin6len);
sainfo.ai_flags = 0;
sainfo.ai_family = AF_UNSPEC;
sainfo.ai_socktype = SOCK_DGRAM;
sainfo.ai_protocol = IPPROTO_UDP;
status = getaddrinfo(ADDR, PORT, &sainfo, &psinfo);
struct ipv6_mreq ipv6;
ipv6.ipv6mr_interface = interface_index;
if((setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (const void *) &ipv6.ipv6mr_interface,
sizeof(ipv6.ipv6mr_interface))) < 0) {
perror("Setting local interface error");
}
if (use_connect_and_send) {
status = connect(sock, (struct sockaddr *)psinfo->ai_addr, sin6len);
if(status != 0) {
perror("connect failed");
exit(EXIT_FAILURE);
}
status = send(sock, buffer, strlen(buffer), 0);
} else {
status = sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)psinfo->ai_addr, sin6len);
}
if (status < 0) {
perror("send failed");
}
printf("buffer : %s \t%d\n", buffer, status);
// free memory
freeaddrinfo(psinfo);
psinfo = NULL;
shutdown(sock, 2);
close(sock);
return 0;
}
int main(int argc, char* argv[]) {
if(argc < 2) {
printf("specify wheter or not to use sendto (0) or connect+send (1)\n");
exit(EXIT_FAILURE);
}
int use_connect_and_send = atoi(argv[1]);
int interface_index = 0;
if(argc > 2) {
interface_index = if_nametoindex(argv[2]);
if (interface_index == 0) {
perror("nametoindex failed, does the given interface exist?");
}
}
client(use_connect_and_send, interface_index);
}
问题
你知道我在这种情况下做错了什么<强>连接 +发送(a)?为什么它的行为与sendto
在默认接口中取得成功的情况有所不同?
Problem description
I'm currently trying to set up an ipv6 client/server UDP communication with multicast.
connect + send
The problem I'm facing occurs during the connect
call for ipv6 UDP multicast socket:
- (a) If I choose the default interface
0
withsetsockopt
andIPV6_MULTICAST_IF
the connect call will fail. - (b) If I choose an interface index that corresponds to one actual active multicast interface in my system (e.g.
ìf_nametoindex("eth0")
) then it will succeed.
sendto
When using sendto
without a prior connect
for the destination address it will succeed in both cases with the default interface 0
(a) or a corresponding interface via if_nametoindex
(b).
Example
The example showcases the four possibilities of running the client to send to a multicast address. Compile and run:
- connect + send (a):
./main 1
- Fails with: Invalid argument - connect + send (b):
./main 1 eth0
- Succeeds - sendto (a):
./main 0
- Succeeds - sendto (b):
./main 0 eth0
- Succeeds
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <arpa/inet.h>
#define MAXBUF 65536
#define ADDR "ff02::1:5"
#define PORT "50000"
int client(int use_connect_and_send, int interface_index) {
int sock;
int status;
struct addrinfo sainfo, *psinfo, *linfo;
struct sockaddr_in6 sin6;
int sin6len;
char buffer[MAXBUF];
sprintf(buffer, "hello");
sin6len = sizeof(struct sockaddr_in6);
sock = socket(AF_INET6, SOCK_DGRAM, 0);
memset(&sin6, 0, sizeof(struct sockaddr_in6));
sin6.sin6_port = htons(0);
sin6.sin6_family = AF_INET6;
sin6.sin6_addr = in6addr_any;
memset(&sainfo, 0, sizeof(struct addrinfo));
memset(&sin6, 0, sin6len);
sainfo.ai_flags = 0;
sainfo.ai_family = AF_UNSPEC;
sainfo.ai_socktype = SOCK_DGRAM;
sainfo.ai_protocol = IPPROTO_UDP;
status = getaddrinfo(ADDR, PORT, &sainfo, &psinfo);
struct ipv6_mreq ipv6;
ipv6.ipv6mr_interface = interface_index;
if((setsockopt(sock, IPPROTO_IPV6, IPV6_MULTICAST_IF, (const void *) &ipv6.ipv6mr_interface,
sizeof(ipv6.ipv6mr_interface))) < 0) {
perror("Setting local interface error");
}
if (use_connect_and_send) {
status = connect(sock, (struct sockaddr *)psinfo->ai_addr, sin6len);
if(status != 0) {
perror("connect failed");
exit(EXIT_FAILURE);
}
status = send(sock, buffer, strlen(buffer), 0);
} else {
status = sendto(sock, buffer, strlen(buffer), 0,
(struct sockaddr *)psinfo->ai_addr, sin6len);
}
if (status < 0) {
perror("send failed");
}
printf("buffer : %s \t%d\n", buffer, status);
// free memory
freeaddrinfo(psinfo);
psinfo = NULL;
shutdown(sock, 2);
close(sock);
return 0;
}
int main(int argc, char* argv[]) {
if(argc < 2) {
printf("specify wheter or not to use sendto (0) or connect+send (1)\n");
exit(EXIT_FAILURE);
}
int use_connect_and_send = atoi(argv[1]);
int interface_index = 0;
if(argc > 2) {
interface_index = if_nametoindex(argv[2]);
if (interface_index == 0) {
perror("nametoindex failed, does the given interface exist?");
}
}
client(use_connect_and_send, interface_index);
}
Question
Do you know what I'm doing wrong in the case connect + send (a) ? Why does it behave differently from sendto
which succeeds with the default interface?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论