socket 实现udp组播通信

socket 实现udp组播通信

UDP组播(Multicast)是一种网络通信方式,它允许一个发送者(源)发送单一的数据包到多个接收者(目标)。与单播(Unicast)通信(其中数据包从一个发送者发送到一个接收者)和广播(Broadcast)通信(其中数据包发送到网络中的所有设备)不同,组播提供了一种中间方式,其中数据包被发送到一组特定的接收者。

以下是UDP组播的一些关键点:

  1. IP地址范围:组播使用特殊的IP地址范围(在IPv4中,范围是224.0.0.0到239.255.255.255)。这些地址不直接对应到任何物理设备,而是表示一个组或集合。
  2. 效率:与广播相比,组播更加高效,因为它只将数据发送到一组特定的接收者,而不是整个网络。
  3. 路由器处理:路由器可以智能地处理组播数据包,根据路由表决定哪些设备应该接收这些数据包。这意味着组播数据包不会在网络中无限制地传播。
  4. 应用:UDP组播常用于需要一对多通信的应用场景,如视频会议、网络电视、游戏等。
  5. UDP与TCP:UDP组播通常与UDP(用户数据报协议)一起使用,因为UDP是无连接的,不需要在发送者和接收者之间建立连接。相比之下,TCP(传输控制协议)是有连接的,并且不支持组播。
  6. 组播组:一个组播组是一组想要接收特定组播数据包的网络设备。这些设备需要加入或订阅该组播组才能接收数据。

udp组播客户端代码示例(发送端)

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/ip.h>
#include <arpa/inet.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>

#define MULTICAST_GROUP "224.88.88.88"//组播的ip地址
#define PORT 6666
// 运行客户端可执行文件   ./xxx  服务器端口  服务器地址

int main(int argc,char *argv[])
{

	//1.创建UDP套接字             
	int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if (udp_socket == -1)
	{
		fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno));
		exit(1);
	}

	//2.向目标主机发送消息,需要设置目标端口和目标地址
	char buf[300] = {0};
	
	struct sockaddr_in  dest_addr;
	dest_addr.sin_family 		= AF_INET; 						//协议族,是固定的
 	dest_addr.sin_addr.s_addr  =inet_addr(MULTICAST_GROUP);			//服务器地址 "192.168.64.xxx"  
	dest_addr.sin_port   		= htons(PORT);			//服务器端口,必须转换为网络字节序


	//3.发送客户端的上线时间
    while (1) 
 {
    
    fgets(buf, sizeof(buf), stdin);
    sendto(udp_socket,buf,strlen(buf),0, (struct sockaddr *)&dest_addr, sizeof(dest_addr));
     
 }
	


	return 0;

}

udp组播服务器端代码示例(接收端)

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <errno.h>
#include <netinet/ip.h>
#include <netinet/udp.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */



#define PORT 6666

int main(int argc,char *argv[])
{
	
	//1.创建UDP套接字             
	int udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if (udp_socket == -1)
	{
		fprintf(stderr, "udp socket error,errno:%d,%s\n",errno,strerror(errno));
		exit(1);
	}

  struct sockaddr_in  host_addr;

	host_addr.sin_family 		= AF_INET; 					      	//协议族,是固定的
	host_addr.sin_port   		= htons(PORT);			        //目标端口,必须转换为网络字节序
	host_addr.sin_addr.s_addr   = htonl(INADDR_ANY);		

	//2.需要先绑定服务器的端口和地址
	struct ip_mreq mreq;
   mreq.imr_multiaddr.s_addr = inet_addr("224.88.88.88");
   mreq.imr_interface.s_addr = htonl(INADDR_ANY);
  
  setsockopt(udp_socket, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
  

	bind(udp_socket,(struct sockaddr *)&host_addr, sizeof(host_addr));

	//3.调用recvfrom等待接收数据,并且接收客户端的网络信息
	char buf[128] = {0};
	struct sockaddr_in  client;
	socklen_t client_len = sizeof(client);
     

	while(1)
	{
int bytes_received = recvfrom(udp_socket, buf, sizeof(buf),0, (structsockaddr*)&client,&client_len);
    if(bytes_received == -1)
    {
      perror("recvfrom error");
        continue;
    }

    printf("Received %d bytes from [%s]: %s\n", bytes_received, inet_ntoa(client.sin_addr), buf);
    bzero(buf, sizeof(buf));
	}
	
	return 0;

}

以上代码我们需要先编译服务器端的代码并运行:

gcc udp_server_group.c -o udp_server_group

./udp_server_group

然后编译运行客户端的代码:

gcc udp_client_group.c -o udp_client_group

./udp_client_group

需要注意的是,虽然UDP组播在某些场景下很有用,但它也有一些限制和挑战,如网络拥塞、数据丢失和安全性问题。因此,在设计和实施基于UDP组播的系统时,需要仔细考虑这些方面。

如果代码用法有什么问题,请将问题发至网易邮箱 m17872844806@163.com,作者将及时改正,欢迎与各位老爷交流讨论。

麻烦三连加关注!!!!

比心

posted @   琨为玉也  阅读(951)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示