组播发送和组播接收的源代码例子【转】

86 篇文章 4 订阅
2 篇文章 0 订阅

组播原理这里就不介绍了, 我博客里有介绍组播原理的详细的文章。

这里只是实现一个小例子, 一个 send.cpp 一个recv.cpp文件。

编译后生成2个进程, 一个接收一个发送。

Sender.cpp 文件内容如下:

#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define HELLO_PORT 12345
#define HELLO_GROUP "225.0.0.37"

int main(int argc, char *argv[])
{
	struct sockaddr_in addr;
	int fd, cnt;
	struct ip_mreq mreq;
	char *message="Hello, World!";

	/* create what looks like an ordinary UDP socket */
	if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) 
	{
		perror("socket");
		exit(1);
	}

	/* set up destination address */
	memset(&addr,0,sizeof(addr));
	addr.sin_family=AF_INET;
	addr.sin_addr.s_addr=inet_addr(HELLO_GROUP);
	addr.sin_port=htons(HELLO_PORT);

	/* now just sendto() our destination! */
	while (1)
	{
		if (sendto(fd,message, strlen(message), 0, (struct sockaddr *) &addr, sizeof(addr)) < 0) 
		{
			perror("sendto");
			exit(1);
		}
		sleep(1);
	}
}

Recver.cpp 文件内容如下:

#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>

#define HELLO_PORT  12345
#define HELLO_GROUP "225.0.0.37"
#define MSGBUFSIZE 256

int main(int argc, char *argv[])
{
	struct sockaddr_in addr;
	int fd, nbytes,addrlen;
	struct ip_mreq mreq;
	char msgbuf[MSGBUFSIZE];

	u_int yes=1; /*** MODIFICATION TO ORIGINAL */

	/* create what looks like an ordinary UDP socket */
	if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) 
	{
		perror("socket");
		exit(1);
	}


	/**** MODIFICATION TO ORIGINAL */
	/* allow multiple sockets to use the same PORT number */
	if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) 
	{
		perror("Reusing ADDR failed");
		exit(1);
	}
	/*** END OF MODIFICATION TO ORIGINAL */

	/* set up destination address */
	memset(&addr,0,sizeof(addr));
	addr.sin_family=AF_INET;
	addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
	addr.sin_port=htons(HELLO_PORT);

	/* bind to receive address */
	if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0)
	{
		perror("bind");
		exit(1);
	}

	/* use setsockopt() to request that the kernel join a multicast group */
	mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
	mreq.imr_interface.s_addr=htonl(INADDR_ANY);
	if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) 
	{
		perror("setsockopt");
		exit(1);
	}

	/* now just enter a read-print loop */
	while (1) 
	{
		addrlen=sizeof(addr);
		if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0, (struct sockaddr *) &addr,(socklen_t*)&addrlen)) < 0) 
		{
			perror("recvfrom");
			exit(1);
		}
		puts(msgbuf);
	}

	return 0;
}

Makefie 文件如下 :

CC = gcc
CXX = g++
CFLAGS = -Wall -D_DEBUG -DDEBUG -g -O0
LDFLAGS = 

MODULE_INC = -I/usr/include
MODULE_LIB = -L/usr/lib

CFLAGS  += $(MODULE_INC)
LDFLAGS += $(MODULE_LIB)


SENDOBJS = Sender.o
RECVOBJS = Recver.o


TARGET = Sender Recver

all: $(TARGET)

Sender: $(SENDOBJS)
	$(CXX) -o $@ $^ $(LDFLAGS)

Recver: $(RECVOBJS)
	$(CXX) -o $@ $^ $(LDFLAGS)

clean: 
	rm -f *.o
	rm -f $(TARGET)
	rm -f http/*.o
# make rule
%.o : %.c
	$(CC) $(CFLAGS) -c $^ -o $@	

%.o : %.cpp
	$(CC) $(CFLAGS) -c $^ -o $@	

编译方法直接

make

下来执行

./Sender 

./Recver

即可看到输出的结果。。。。

 

---------------------------------------------------------------------------------------------------

 修改过的  Recver.c   , 接收二进制数据, 接受传入参数?

    #include <stdlib.h>  
    #include <sys/types.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <arpa/inet.h>  
    #include <time.h>  
    #include <string.h>  
    #include <stdio.h>  
    #include <unistd.h>  
      
    //#define HELLO_PORT  12345  
    //#define HELLO_GROUP "225.0.0.37"  
    #define MSGBUFSIZE 32*1024  
      
    int main(int argc, char *argv[])  
    {  
		if (argc != 4)
		{
			printf ("%s  mulitAddr  port  bindIP\n");
			exit(129);
		}
		char* multiAddr = argv[1];
		int port = atoi(argv[2]);
		char* bindIP = argv[3];
		
		printf ("%s:%d\n", multiAddr, port);
		printf ("bindIP = %s\n", bindIP);
		
        struct sockaddr_in addr;  
        int fd, nbytes,addrlen;  
        struct ip_mreq mreq;  
        char msgbuf[MSGBUFSIZE];  
      
        u_int yes=1; /*** MODIFICATION TO ORIGINAL */  
      
        /* create what looks like an ordinary UDP socket */  
        if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0)   
        {  
            perror("socket");  
            exit(1);  
        }  
      
      
        /**** MODIFICATION TO ORIGINAL */  
        /* allow multiple sockets to use the same PORT number */  
        if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0)   
        {  
            perror("Reusing ADDR failed");  
            exit(1);  
        }  
        /*** END OF MODIFICATION TO ORIGINAL */  
      
		unsigned long nip = inet_addr (bindIP);
        /* set up destination address */  
        memset(&addr,0,sizeof(addr));  
        addr.sin_family=AF_INET;  
        addr.sin_addr.s_addr=INADDR_ANY; /* N.B.: differs from sender */  
        addr.sin_port=htons(port);  
      
        /* bind to receive address */  
        if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0)  
        {  
            perror("bind");  
            exit(1);  
        }  
      
        /* use setsockopt() to request that the kernel join a multicast group */  
        mreq.imr_multiaddr.s_addr=inet_addr(multiAddr);  
        mreq.imr_interface.s_addr=inet_addr(bindIP);//htonl(INADDR_ANY);  
        if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0)   
        {  
            perror("setsockopt");  
            exit(1);  
        }  
      
	    FILE* fp = fopen ("./xxxx.ts", "w+");
        /* now just enter a read-print loop */  
        while (1)   
        {  
            addrlen=sizeof(addr);  
            if ((nbytes=recvfrom(fd, msgbuf, MSGBUFSIZE, 0, (struct sockaddr *) &addr,(socklen_t*)&addrlen)) < 0)   
            {  
                perror("recvfrom");  
                exit(1);  
            }  
            fwrite (msgbuf, 1, nbytes, fp);
			printf ("write data %d bytes\n", nbytes);
        }  
      
        return 0;  
    }  


UDP (User Datagram Protocol) 是无连接的协议,并不像TCP那样提供端到端的可靠传输服务。因此,当接收UDP多播数据时,你并不能直接获取发送方的IP地址,因为UDP包头并不包含源IP信息。多播包通常会被网络设备分发给所有已订阅该组播地址的目标主机,而不追踪发送者。 然而,在某些特定的应用场景下,比如使用UDG (User Datagram Gateway) 或者通过一些中间代理服务器,你可以尝试利用这些服务提供的元数据来间接获取发送方的信息。例如,如果服务器维护了一个映射表,将多播地址关联到一组发送者,则可以从这个表中查找。 在编程层面,如果你需要这种高级功能,可以考虑使用支持多播的库或者API,它们可能会提供额外的服务来帮助处理。例如在Python的`socket`模块中,虽然原始的UDP socket无法提供源IP,但有些库如`PyMulticast`可能会记录这样的信息。 ```python import PyMulticast # 创建多播接收器 group = 'your_multicast_address' receiver = PyMulticast.MultiCastReceiver(group) # 注册接收回调 def on_data_received(ip, port, data): print(f"Received from IP: {ip}") receiver.register_callback(on_data_received) receiver.join_group() # 开始接收数据 receiver.run_forever() ``` 在这个例子中,你需要查看`on_data_received`函数中的`ip`参数来获取发送方的IP。但是请注意,这依赖于所使用的库是否提供了这样的功能。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值