Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UDP组播支持 #468

Open
x1244 opened this issue Nov 28, 2023 · 7 comments
Open

UDP组播支持 #468

x1244 opened this issue Nov 28, 2023 · 7 comments

Comments

@x1244
Copy link

x1244 commented Nov 28, 2023

#251 中看到有UDP组播需求,我这里也正好有这个需求。
仿udp_broadcast()接口实现了一个。名称参考Qt的joinMulticastGroup()leaveMulticastGroup()接口,但区分IPv4和IPv6两个版本。总共4个接口

HV_INLINE int udp_joinmulticastgroupv4(int sockfd, const char* group, const char* local_host);
HV_INLINE int udp_leavemulticastgroupv4(int sockfd, const char* group, const char* local_host);
HV_INLINE int udp_joinmulticastgroupv6(int sockfd, const char* group, ULONG interface);
HV_INLINE int udp_leavemulticastgroupv6(int sockfd, const char* group, ULONG interface);

能否提个PR过来,添加到哪个分支,放在hsocket.h中作为HV_INLINE是合适?
请您给个指示。
实现如下

HV_INLNE int udp_joinmulticastgroupv4(int sockfd, const char* group, const char* local_host) {
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(group);
    mreq.imr_interface.s_addr = inet_addr(local_host);
    return setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq));
}
HV_INLNE int udp_leavemulticastgroupv4(int sockfd, const char* group, const char* local_host) {
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(group);
    mreq.imr_interface.s_addr = inet_addr(local_host);
    return setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char*)&mreq, sizeof(mreq));
}
HV_INLNE int udp_joinmulticastgroupv6(int sockfd, const char* group, ULONG interface) {
    struct ipv6_mreq mreq;
    mreq.ipv6mr_interface = interface; 
    inet_pton(AF_INET6, group, &mreq.ipv6mr_multiaddr);
    return setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq));
}
HV_INLNE int udp_leavemulticastgroupv6(int sockfd, const char* group, ULONG interface) {
    struct ipv6_mreq mreq;
    mreq.ipv6mr_interface = interface; 
    inet_pton(AF_INET6, group, &mreq.ipv6mr_multiaddr);
    return setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (const char*)&mreq, sizeof(mreq));
}
@ithewei
Copy link
Owner

ithewei commented Dec 21, 2023

欢迎提PR,可以提到master分支

@paleomoon
Copy link

大佬快提pr啊,我也有这个需求

@x1244
Copy link
Author

x1244 commented Dec 25, 2023

我这里名字还没想好,这个名字太长了。
还有测试还没怎么做,只有IPV4的组播加入和离开试了一下。
如果你着急用,下边这些代码可以加入你程序里,自行编译顶着先。
添加一个头文件或实现文件,或放到UdpClinet.h

int udp_joinmulticastgroupv4(int sockfd, const char* group, const char* local_host) {
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(group);
    mreq.imr_interface.s_addr = inet_addr(local_host);
    return setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq));
}
int udp_leavemulticastgroupv4(int sockfd, const char* group, const char* local_host) {
    struct ip_mreq mreq;
    mreq.imr_multiaddr.s_addr = inet_addr(group);
    mreq.imr_interface.s_addr = inet_addr(local_host);
    return setsockopt(sockfd, IPPROTO_IP, IP_DROP_MEMBERSHIP, (const char*)&mreq, sizeof(mreq));
}
int udp_joinmulticastgroupv6(int sockfd, const char* group, ULONG interface) {
    struct ipv6_mreq mreq;
    mreq.ipv6mr_interface = interface; 
    inet_pton(AF_INET6, group, &mreq.ipv6mr_multiaddr);
    return setsockopt(sockfd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq));
}
int udp_leavemulticastgroupv6(int sockfd, const char* group, ULONG interface) {
    struct ipv6_mreq mreq;
    mreq.ipv6mr_interface = interface; 
    inet_pton(AF_INET6, group, &mreq.ipv6mr_multiaddr);
    return setsockopt(sockfd, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (const char*)&mreq, sizeof(mreq));
}

UdpClient.h文件class UdpClientEventLoopTmpl中添加

	//multicast group
	int joinmulticastgroupv4(const char* group, const char* local_host = "0.0.0.0"){
		return udp_joinmulticastgroupv4(channel->fd(), group, local_host);
	}

然后在主程序文件UdpClient_test.cpp中添加

	int gport = atoi(argv[2]);
        cli.bind(gport, "0.0.0.0");
	std::cout <<"bind local port:" <<gport <<std::endl;
	cli.joinmulticastgroupv4("230.1.1.25", "0.0.0.0");

基本就可以了。
这是我测试组播发送的一个截图
image

@paleomoon
Copy link

好的,谢谢大佬

@x1244
Copy link
Author

x1244 commented Jan 1, 2024

我已经添加了UDP组播的加入和离开方法,并进行了测试。
PR在 #480

@rorschach-py
Copy link

我已经添加了UDP组播的加入和离开方法,并进行了测试。 PR在 #480

interface 为啥有的是 ULONG 有的是 char* ?

@x1244
Copy link
Author

x1244 commented Jan 5, 2024

IPV4是描述绑定本机IP的地址,是char*。
IPV6是描述绑定本机接口,是ULONG。
这是根据 ip_mreqipv6_mreq的不同结构体定义给出的,这样更直接,没有转换。
网上搜到是这个结构体,我就用上了。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants