目录
一、UDP组播介绍
1.UDP介绍
2.UDP组播
3.组播地址
4.组播的原理:
二、UDP组播编程
1.UDP组播的基本步骤
2.加入组播组-setsockopt
三、UDP组播服务端代码实现
1.代码实现
2.运行结果
四、UDP单播客户端代码实现
1.代码实现
2.运行结果
一、UDP组播介绍
1.UDP介绍
UDP协议进行信息的传输之前不需要建议连接。换句话说就是客户端向服务器发送信息,客户端只需要给出服务器的ip地址和端口号,然后将信息封装到一个待发送的报文中并且发送出去。至于服务器端是否存在,或者能否收到该报文,客户端根本不用管。更多UDP详细介绍可以查看:Linux网络编程-UDP协议详解
2.UDP组播
组播是一对多的传输方式,其中有个组播组的概念,发送端将数据向一个组内发送,网络中的路由器通过底层的IGMP协议自动将数据发送到所有监听这个组的终端。至于广播则和组播有一些相似,区别是路由器向子网内的每一个终端都投递一份数据包,不论这些终端是否乐于接收该数据包。UDP广播只能在内网(同一网段)有效,而组播可以较好实现跨网段群发数据。
UDP组播是采用的无连接,数据报的连接方式,所以是不可靠的。也就是数据能不能到达接受端和数据到达的顺序都是不能保证的。但是由于UDP不用保证数据 的可靠性,所有数据的传送效率是很快的。
然而在ip组播环中,数据包的目的地址不是一个,而是一组,形成组地址。所有的信息接收者都加入到一个组内,并且一旦加入之后,流向组地址的数据立即开始向接收者传输,组中的所有成员都能接收到数据包。组播组中的成员是动态的,主机可以在任何时刻加入和离开组播组。
用同一个IP多播地址接收多播数据包的所有主机构成了一个主机组,也称为多播组。一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。此外,不属于某一个多播组的主机也可以向该多播组发送数据包。
3.组播地址
组播组可以是永久的也可以是临时的,组播组地址中,有一部分由官方分配的,称为永久组播组。永久组播组保持不变的是它的ip地址,组中的成员构成可以发生变化。永久组播组中成员的数量都可以是任意的,甚至可以为零。那些没有保留下来供永久组播组使用的ip组播地址,可以被临时组播组利用。
IP地址 | |
244.0.0.0~244.0.0.255 | 局部链接多播地址:是为路由协议和其它用途保留的地址,路由器并不转发属于此范围的IP包 |
244.0.1.0~244.0.1.255 | 预留多播地址:公用组播地址,可用于Internet;使用前需要申请 |
244.0.2.0~238.255.255.255 | 预留多播地址:用户可用组播地址(临时组地址),全网范围内有效 |
239.0.0.0~239.255.255.255 | 本地管理组播地址,可供组织内部使用,类似于私有 IP 地址,不能用于 Internet,可限制多播范围 |
4.组播的原理:
组播首先由一个用户申请一个组播组,这个组播组被维护在路由器中,其他用户申请加入组播组,这样当一个用户向组内发送消息时,路由器将消息转发给组内的所有成员。如果申请加入的组不在本级路由中,如果路由器和交换机允许组播协议通过,路由器将申请加入的操作向上级路由提交。广域网通信要经过多级路由器和交换机,几乎所有的网络设备都默认阻止组播协议通过(只允许本网段内,不向上级提交),这使得广域网上实现组播有一定局限。
二、UDP组播编程
UDP组播相对于单播而言,多了一个加入组播组的过程,这里只对加入组播组函数说明,其他函数可以查看博主文章:Linux网络编程-UDP单播_ProYuan的博客-CSDN博客
1.UDP组播的基本步骤
- 建立socket
- socket和端口绑定
- 加入一个组播组
- 通过sendto / recvfrom进行数据的收发
- 关闭socket
2.加入组播组-setsockopt
int setsockopt(int sockfd, int level,int optname,const void *optval, socklen_t optlen);
返回值:成功执行返回0,否则返回-1
三、UDP组播服务端代码实现
1.代码实现
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUF_SIZE 88
#define PORT 55555
#define ADDR "192.168.111.213"
#define MUNICASTADDR "236.9.9.9"
int main(int argc, char *argv[])
{
//建立套接字
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); //IPV4,数据报套接字类型,不指定协议
//说明本服务器地址
struct sockaddr_in srvaddr;
srvaddr.sin_family = AF_INET, //协议类型IPV4
srvaddr.sin_port = htons(PORT), //端口号-网络字节序
srvaddr.sin_addr.s_addr = htonl(INADDR_ANY); //IP地址-任意地址
//绑定地址
bind(sock_fd, (const struct sockaddr *)&srvaddr, sizeof(srvaddr));
srvaddr.sin_addr.s_addr = inet_addr(ADDR);
setsockopt(sock_fd, IPPROTO_IP, IP_MULTICAST_IF, (void*)&srvaddr,sizeof(struct sockaddr_in));
struct ip_mreq ipMreq;
ipMreq.imr_interface.s_addr = inet_addr(ADDR);
ipMreq.imr_multiaddr.s_addr = inet_addr(MUNICASTADDR);
//接收数据
char buf[BUF_SIZE] = { 0 };
struct sockaddr_in cliaddr;
socklen_t cliaddrlen = sizeof(cliaddr);
while (1)
{
bzero(buf, BUF_SIZE);
bzero(&cliaddr, cliaddrlen);
recvfrom(sock_fd, buf, BUF_SIZE, 0, (struct sockaddr *)&cliaddr, &cliaddrlen);
printf("udp server from [%s - %hu]:%s\n",inet_ntoa(cliaddr.sin_addr),cliaddr.sin_port,buf);
}
//关闭套接字
close(sock_fd);
return 0;
}
2.运行结果
四、UDP单播客户端代码实现
1.代码实现
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define BUF_SIZE 88
#define PROT 55555
#define ADDR "192.168.111.213"
#define MUNICASTADDR "236.9.9.9"
int main(int argc, char *argv[])
{
//建立套接字
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0); //IPV4,数据报套接字类型,不指定协议
//声明将连接地址
struct sockaddr_in srvaddr;
srvaddr.sin_family = AF_INET, //协议类型IPV4
srvaddr.sin_port = htons(PROT), //端口号-网络字节序
srvaddr.sin_addr.s_addr = inet_addr(ADDR); //IP地址-字符串转IP
struct ip_mreq ipMreq;
setsockopt(sock_fd, IPPROTO_IP, IP_MULTICAST_IF, (void*)&srvaddr,
sizeof(struct sockaddr_in));
ipMreq.imr_interface.s_addr = inet_addr(ADDR);
ipMreq.imr_multiaddr.s_addr = inet_addr(MUNICASTADDR);
setsockopt(sock_fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &ipMreq, sizeof(ipMreq));
//发送数据
char buf[BUF_SIZE] = { 0 };
int count = 0;
while (1)
{
memset(buf,0, BUF_SIZE);
sprintf(buf, "%d",count);
printf("udp client send:[%s - %d]:%s\n",ADDR,PROT,buf);
sendto(sock_fd, buf, strlen(buf), 0, (const struct sockaddr*)&srvaddr, sizeof(srvaddr));
count++;
sleep(1);
}
//关闭套接字
close(sock_fd);
return 0;
}
2.运行结果
更多推荐
Linux网络编程-UDP组播服务客户端代码实现
发布评论