socket 实现udp组播通信
UDP组播(Multicast)是一种网络通信方式,它允许一个发送者(源)发送单一的数据包到多个接收者(目标)。与单播(Unicast)通信(其中数据包从一个发送者发送到一个接收者)和广播(Broadcast)通信(其中数据包发送到网络中的所有设备)不同,组播提供了一种中间方式,其中数据包被发送到一组特定的接收者。
以下是UDP组播的一些关键点:
- IP地址范围:组播使用特殊的IP地址范围(在IPv4中,范围是224.0.0.0到239.255.255.255)。这些地址不直接对应到任何物理设备,而是表示一个组或集合。
- 效率:与广播相比,组播更加高效,因为它只将数据发送到一组特定的接收者,而不是整个网络。
- 路由器处理:路由器可以智能地处理组播数据包,根据路由表决定哪些设备应该接收这些数据包。这意味着组播数据包不会在网络中无限制地传播。
- 应用:UDP组播常用于需要一对多通信的应用场景,如视频会议、网络电视、游戏等。
- UDP与TCP:UDP组播通常与UDP(用户数据报协议)一起使用,因为UDP是无连接的,不需要在发送者和接收者之间建立连接。相比之下,TCP(传输控制协议)是有连接的,并且不支持组播。
- 组播组:一个组播组是一组想要接收特定组播数据包的网络设备。这些设备需要加入或订阅该组播组才能接收数据。
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组播的系统时,需要仔细考虑这些方面。
如果代码用法有什么问题,请将问题发至网易邮箱 [email protected],作者将及时改正,欢迎与各位老爷交流讨论。
麻烦三连加关注!!!!
比心
标签:udp,组播,socket,include,buf,addr From: https://www.cnblogs.com/zkbklink/p/18235982