首页 > 编程知识 正文

java udp socket,tcpudp测试工具组播说明书

时间:2023-05-04 13:34:04 阅读:174690 作者:2141

1. 概述

1.1单播用于两个主机之间的一对一通信

1.2广播用于将单个主机数据通信到局域网上的所有主机

1.3单播和广播两个极端,要么对一台主机进行通信,要么对整个局域网的主机进行通信

1.4实际上,经常需要与一组特定的主机进行通信,而不是与所有局域网上的主机进行通信,在这种情况下有多播

1.5IP多播(也称为多播或多播)是使得一个或更多主机能够向多个主机发送包的TCP/IP网络技术。

1.6组播是IPv6包的三种基本目的地地址类型之一,组播是单点对多点通信。 IPv6不采用IPv4中的多播术语,将广播视为多播的特殊例子。

2.组播的特点

组播也可以说是组播。 这也是UDP的特性之一。 多播是主机之间的一种一对多的通信模式,是一个或多个多播源可以向多个接收者发送同一消息的技术。 组播源向特定的组播地址发送消息。 多播地址与单播地址不同,它属于一组主机,而不是特定的主机。 多播地址代表一个组,所有需要接收多播消息的收件人都加入该组。

广播只能在局域网接入内使用,多播可以在局域网或广域网中使用

发送广播消息时,连接到局域网的客户端会在不需要的情况下接收广播数据。 组播可以控制发送方的消息在哪个接收方可以接收,更灵活、更人性化。

广播必须使用广播地址,多播必须使用多播地址。

默认情况下,广播和多播属性处于禁用状态,必须在setsockopt ()函数中进行设置才能使用。

必须使用多播地址,对于IPv4,范围为224.0.0.0到239.255.255.255.255.255,包括本地链路多播地址、保留多播地址和管理权限妈妈

224.0.0.0 ~ 224.0.0.255:本地链路多播地址:为路由协议和其他用途保留的地址。

只能在局域网上使用。 不转发路由器的地址224.0.0.0不可用。 这是预约地址

224.0.1.0 ~ 224.0.1.255:是互联网上的。

224.0.2.0 ~ 238.255.255.255:用户可以使用的多播地址(临时组地址)在整个网络中有效

239.0.0.0 ~ 239.255.255.255:是本地管理多播地址,仅在特定的本地范围内有效

组播地址不属于任何服务器或个人,就像微信组号码一样,向任何成员(组播源)或微信组)发送消息(组播IP ),并将其发送给该组的成员

3.组播应用

3.1点对多点应用

点到多点应用是指一个发送者、多个接收者的应用形式,它是最常见的多播APP形式。 典型的APP应用包括媒体广播、媒体推送、信息缓存、事件通知和状态监视。

3.2多点APP沟通

点对点APP应用程序是一种多发件人、单收件人的APP应用程序格式。 通常是双向请求响应APP应用程序,其中任何一方(多个点或点)都可能启动请求。 典型的应用是资源检索、数据收集、网络拍卖、信息查询等。

3.3多点对多点应用

多点对多点应用是指多发件人和多收件人的应用形式。 通常,各接收者可以接收从多个发送者发送的数据,另外,各发送者可以向多个接收者发送数据。 典型的应用有多点会议、资源同步、并行处理、协同处理、远程学习、讨论组、分布式交互仿真(流畅哑铃)、多人游戏等

4. 设置组播属性

使用多播传输数据时,无论是消息发送方和接收方,都必须设置相关的属性。 设定函数使用相同的东西。 也就是说,setsockopt (,函数的原型如下:

intsetsockopt(intsockfd,int level,int optname,const void *optval,socklen_t optlen ); 4.1发送方

发送多播消息的一方必须设置多播属性。 具体的设定方法如下。

/* struct in _ addr { in _ addr _ ts _ addr; //unsigned int}; //*函数: setsockopt描述:发送方UDP多播属性参数: sockfd:UDP通信套接字level :要设置套接字级别和设置多播属性,请输入IP ptoto _ ipopt 要设置多播属性,必须将此参数指定为IP_MULTICAST_IFoptval。 设置多播属性。 此指针必须指向存储多播地址的struct in_addr{}类型的结构地址,多播地址的存储方法是大字节序。 optlen:optval指针指向的内存大小,即sizeof(structin_addr )返回值:函数调用成功返回0,调用失败,返回- 1*/struct in_addr opt; //如果将多播地址初始化为该结构成员,则返回inet_Pton(af_

INET, GROUP_IP, &opt.s_addr); setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &opt, sizeof(opt));

4.2 接收端
因为一个组播地址表示一个群组,所以需要接收组播报文的接收者都加入这个群组,和想要接收群消息就必须要先入群是一个道理。加入到这个组播群组的方式如下:

/*struct in_addr{ in_addr_t s_addr;// unsigned int};struct ip_mreqn{ struct in_addr imr_multiaddr; // 组播地址/多播地址 struct in_addr imr_address; // 本地地址 int imr_ifindex; // 网卡的编号, 每个网卡都有一个编号};// 必须通过网卡名字才能得到网卡的编号: 可以通过 ifconfig 命令查看网卡名字#include <net/if.h>// 将网卡名转换为网卡的编号, 参数是网卡的名字, 比如: "ens33"// 返回值就是网卡的编号unsigned int if_nametoindex(const char *ifname);*//*函数:setsockopt描述:配置接收端UDP组播属性参数:sockfd:基于 udp 的通信的套接字level:套接字级别,加入到多播组该参数需要指定为:IPPTOTO_IPoptname:套接字选项名,加入到多播组该参数需要指定为:IP_ADD_MEMBERSHIPoptval:加入到多播组,这个指针应该指向一个 struct ip_mreqn{} 类型的结构体地址optlen:optval 指向的内存大小,即:sizeof(struct ip_mreqn)*/ struct ip_mreqn opt; // 要加入到哪个多播组, 通过组播地址来区分 inet_pton(AF_INET, GROUP_IP, &opt.imr_multiaddr.s_addr); opt.imr_address.s_addr = htonl(INADDR_ANY); opt.imr_ifindex = if_nametoindex("ens33"); setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));

5. 组播通信流程
发送组播消息的一端需要将数据发送到组播地址和固定的端口上,想要接收组播消息的终端需要绑定对应的固定端口然后加入到组播的群组,最终就可以实现数据的共享。

6.代码举例

6.1 发送端代码

#include <stdio.h>#include <stdlib.h>#include <unistd.h>#include <string.h>#include <arpa/inet.h>#define GROUP_IP "224.0.1.0"//#define GROUP_IP "239.0.1.10"int main(){ // 1. 创建通信的套接字 int fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd == -1) { perror("socket"); exit(0); } // 2. 设置组播属性 (经测试可以不设置发送端组播属性也能正常发送) struct in_addr opt; // 将组播地址初始化到这个结构体成员中即可 inet_pton(AF_INET, GROUP_IP, &opt.s_addr); setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &opt, sizeof(opt)); char buf[1024];char sendaddrbuf[64];socklen_t len = sizeof(struct sockaddr_in);struct sockaddr_in sendaddr; struct sockaddr_in cliaddr; cliaddr.sin_family = AF_INET; cliaddr.sin_port = htons(9999); // 接收端需要绑定9999端口 // 发送组播消息, 需要使用组播地址, 和设置组播属性使用的组播地址一致就可以 inet_pton(AF_INET, GROUP_IP, &cliaddr.sin_addr.s_addr); // 3. 通信 int num = 0; while(1) {memset(buf, 0, sizeof(buf)); sprintf(buf, "hello, client...%dn", num++); // 数据广播 sendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr*)&cliaddr, len); printf("发送的组播的数据: %sn", buf);memset(buf, 0, sizeof(buf));recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sendaddr, &len);printf("sendaddr:%s, prot:%dn", inet_ntop(AF_INET, &sendaddr.sin_addr.s_addr, sendaddrbuf, sizeof(sendaddrbuf)), sendaddr.sin_port);printf("接收到的组播消息: %sn", buf); } close(fd); return 0;}

6.2 接收端代码

#define GROUP_IP "224.0.1.0"//#define GROUP_IP "239.0.1.10"int main(){ // 1. 创建通信的套接字 int fd = socket(AF_INET, SOCK_DGRAM, 0); if(fd == -1) { perror("socket"); exit(0); } // 2. 通信的套接字和本地的IP与端口绑定 struct sockaddr_in addr; addr.sin_family = AF_INET; addr.sin_port = htons(9999); // 大端 addr.sin_addr.s_addr = htonl(INADDR_ANY); // 0.0.0.0 int ret = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); if(ret == -1) { perror("bind"); exit(0); } // 3. 加入到多播组#if 0 //使用struct ip_mreqn或者 struct ip_mreq 设置接收端组播属性都可以正常接收 struct ip_mreqn opt; // 要加入到哪个多播组, 通过组播地址来区分 inet_pton(AF_INET, GROUP_IP, &opt.imr_multiaddr.s_addr); opt.imr_address.s_addr = htonl(INADDR_ANY); opt.imr_ifindex = if_nametoindex("ens33"); setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &opt, sizeof(opt));#elsestruct ip_mreq mreq; // 多播地址结构体mreq.imr_multiaddr.s_addr=inet_addr(GROUP_IP);mreq.imr_interface.s_addr = htonl(INADDR_ANY);ret=setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));#endif char buf[1024];char sendaddrbuf[64];socklen_t len = sizeof(struct sockaddr_in);struct sockaddr_in sendaddr; // 3. 通信 while(1) { // 接收广播消息 memset(buf, 0, sizeof(buf)); // 阻塞等待数据达到 recvfrom(fd, buf, sizeof(buf), 0, (struct sockaddr *)&sendaddr, &len);printf("sendaddr:%s, prot:%dn", inet_ntop(AF_INET, &sendaddr.sin_addr.s_addr, sendaddrbuf, sizeof(sendaddrbuf)), sendaddr.sin_port); printf("接收到的组播消息: %sn", buf);sendto(fd, buf, strlen(buf)+1, 0, (struct sockaddr *)&sendaddr, len); } close(fd); return 0;}

参考于: 苏丙榅:https://subingwen.cn/linux/multicast/#4-1-%E5%8F%91%E9%80%81%E7%AB%AF

参考于:https://blog.csdn.net/weixin_43790540/article/details/104244546

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。