我正在开发基于网络的应用程序,其中我想要接收单播和多播数据。所以我想知道是否可以使用单个套接字接收单播数据和组播数据。这是我的代码,截至目前我只能接收单播数据,但不能接收多播数据。
void* rec(void* t)
{
printf("Rec Thread created\n");
char buf[200];
struct sockaddr_in soc;
soc.sin_family=AF_INET;
soc.sin_addr.s_addr=inet_addr("123.1.2.3");
soc.sin_port=htons(1234);
long sock_fd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
bind(sock_fd,(struct sockaddr *)&soc,sizeof(sockaddr_in));
struct ip_mreq mreq;
memset(&mreq,0,sizeof(struct ip_mreq));
mreq.imr_multiaddr.s_addr=inet_addr("235.5.5.5");
mreq.imr_interface.s_addr=inet_addr("123.1.2.3");
setsockopt(sock_fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq))
while(true)
{
memset(buf,0,sizeof(buf));
long size=recvfrom(sock_fd,buf,200,0,NULL,NULL);
if(size>0)
{
printf("recvd %s\n",buf);
}
else
{
perror("Error receving data");
}
}
}
int main(int argc,char* argv[])
{
pthread_create(&pt,NULL,rec,NULL);
sleep(2);
char buf[]="Hello World!;
struct sockaddr_in soc;
soc.sin_family=AF_INET;
soc.sin_addr.s_addr=inet_addr("123.1.2.3");
soc.sin_port=htons(1234);
long sock_fd=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
sendto(sock_fd,buf,sizeof(buf),0,(struct sockaddr *)&soc,sizeof(sockaddr_in));
struct sockaddr_in msoc;
msoc.sin_family=AF_INET;
msoc.sin_addr.s_addr=inet_addr("235.5.5.5");
msoc.sin_port=htons(1234);
char mbuf[]="Hi All!";
sendto(sock_fd,mbuf,sizeof(mbuf),0,(struct sockaddr *)&msoc,sizeof(sockaddr_in));
return 0;
}
答案 0 :(得分:0)
有可能。或者至少'有点'可能。
请考虑以下代码:
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(void) {
struct sockaddr_in vSSocket;
vSSocket.sin_family = AF_INET;
vSSocket.sin_addr.s_addr = INADDR_ANY;
vSSocket.sin_port = htons(1234);
int vSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (vSocket < 0) {
perror("socket");
return 1;
}
struct ip_mreq vReq;
vReq.imr_multiaddr.s_addr = inet_addr("235.5.5.5");
vReq.imr_interface.s_addr = inet_addr("123.1.2.3");
if (setsockopt(vSocket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &vReq, sizeof(vReq)) < 0) {
perror("setsockopt 2");
return 1;
}
if (bind(vSocket, (struct sockaddr *)&vSSocket, sizeof(vSSocket)) == -1) {
perror("bind");
return 1;
}
ssize_t r;
char vBuf[256];
while (1) {
r = recv(vSocket, vBuf, sizeof(vBuf), 0);
if (r < 0) {
perror("recv");
break;
}
if (memcmp(vBuf, "quit", 4) == 0) {
printf("quit\n");
break;
}
write(1, vBuf, r);
}
return 0;
}
诀窍是:将套接字绑定到INADDR_ANY
地址。因此,它会监听您机器上的每个界面。此外,具有地址123.1.2.3的接口加入多播组235.5.5.5,因此它将接收该地址的任何数据包。
您可以使用精湛的socat
工具测试此解决方案。
要发送到多播地址:
socat STDIO UDP4-DATAGRAM:235.5.5.5:1234
发送到单播地址:
socat STDIO UDP4-DATAGRAM:123.1.2.3:1234
程序应输出您发送给它的任何内容,并在收到以“退出”开头的数据包后退出。
答案 1 :(得分:0)
可以。 nsilent22拥有前90%。
INADDR_ANY
IP_ADD_MEMBERSHIP
(ipv6:IPV6_JOIN_GROUP
)IP_MULTICAST_IF
(ipv6:IPV6_MULTICAST_IF
)来设置多播数据包的输出接口。这将为您提供一个套接字,该套接字侦听多播组,但也接收到计算机的所有单播流量。要将其限制为单个界面,您有两个选择:
IP_PKTINFO
(ipv6:IPV6_RECVPKTINFO
),使用recvmsg接收数据,并根据ipi_ifindex
结构的in_pktinfo
成员(ipv6:{{ ipi6_ifindex
的1}}位成员。struct in6_pktinfo
(需要root特权)这样,您将获得一个套接字,该套接字从选定的多播组接收多播流量以及所有单播流量,但仅限于单个接口。
来源:ip,ipv6和套接字的联机帮助页。