概述
第十四章 多播与广播
14.1 多播
多播接近UDP的实现方式,区别在于多播可以同时向多个主机传递数据。向网络传递1个多播数据包时,路由器将复制该数据包并传递到多个主机(不会向同一个区域发送多个相同数据包,主要用于多媒体数据的实时传输)。
多播组是D类IP地址(224.0.0.0-239.255.255.255)。不少路由器不支持多播,或即便支持也因网络拥堵问题故意阻断多播,为了在不支持多播的路由器中完成多播通信,会使用隧道技术(Tunneling)(这个不是程序员考虑的问题)。
TTL,time to live,是决定数据包传递距离的主要因素,TTL用整数表示,每经过一个路由器就减1,变为0时数据包会被销毁。
将TTL设置为64:
int send_sock;
int time_live = 64;
...
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void*)&time_live, sizeof(time_live));
...
加入多播组:
int recv_sock;
struct ip_mreq join_adr;
...
recv_sock = socket(PF_INET, SOCK_DGRAM, 0);
...
join_adr.imr_multiaddr.s_addr = "多播组地址信息";
join_adr.imr_interface.s_addr = "加入多播组的主机地址信息";
setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&join_adr, sizeof(join_adr));
...
struct ip_mreq{
struct in_addr imr_multiaddr;//写入加入的组IP地址
struct in_addr imr_interface;//加入该组的套接字所属主机的IP地址,也可以使用INADDR_ANY
}
多播中的Sender:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define TTL 64
#define BUF_SIZE 30
void error_handling(char * message);
int main(int argc, char * argv[]){
int send_sock;
struct sockaddr_in mul_adr;
int time_live = TTL;
FILE * fp;
char buf[BUF_SIZE];
if(argc != 3){
printf("Usage : %s <GroupIP> <PORT>n",argv[0]);
exit(1);
}
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
memset(&mul_adr, 0, sizeof(mul_adr));
mul_adr.sin_family = AF_INET;
mul_adr.sin_addr.s_addr = inet_addr(argv[1]);//multicast IP
mul_adr.sin_port = htons(atoi(argv[2]));//multicast port
setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void*)&time_live, sizeof(time_live));
if((fp = fopen("news.txt","r")) == NULL){
error_handling("fopen() error");
}
while(!feof(fp)){
fgets(buf, BUF_SIZE, fp);
sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr*)&mul_adr, sizeof(mul_adr));
sleep(2);
}
fclose(fp);
close(send_sock);
return 0;
}
void error_handling(char *message){
fputs(message, stderr);
fputc('n',stderr);
exit(1);
}
Receiver:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa.h>
#include<sys/socket.h>
#define BUF_SIZE 30
void error_handling(char * message);
int main(int argc, char* argv[]){
int recv_sock;
int str_len;
char buf[BUF_SIZE];
struct sockaddr_in adr;
struct ip_mreq join_adr;
if(argc != 3){
printf("Usage: %s <GroupIP> <PORT> n",argv[0]);
exit(1);
}
recv_sock = socket(PF_INET, SOCK_DGRAM, 0);
memset(&adr, 0, sizeof(adr));
adr.sin_family = AF_INET;
adr.sin_addr.s_addr = htonl(INADDR_ANY);
adr.sin_port = htons(atoi(argv[2]));
if(bind(recv_sock, (struct sockaddr*)&adr, sizeof(adr)) == -1){
error_handling("bind() error!");
}
join_adr.imr_multiaddr.s_addr = inet_addr(argv[1]);
join_adr.im_interface.s_addr = htonl(INADDR_ANY);
setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void*)&join_adr, sizeof(join_adr));
while(1){
str_len = recvfrom(recv_sock, buf, BUF_SIZE-1, 0, NULL, 0);
if(str_len < 0){
break;
}
buf[str_len] = 0;
fputs(buf,stdout);
}
close(recv_sock);
return 0;
}
void error_handling(char* message){
fputs(message,stderr);
fputc('n',stderr);
exit(1);
}
运行:
首先准备好一个news.txt文件,文件中我只写了一句话:
this is a broadcast test!
先运行接收端:
[root@VM_0_10_centos Broadcast]# ./receiver 224.1.1.2 9190 &
在运行发送端:
[root@VM_0_10_centos Broadcast]# ./sender 224.1.1.2 9190
this is a broadcast test!
this is a broadcast test!
[root@VM_0_10_centos Broadcast]#
14.2 广播
也是:一次性向多个主机发送数据。
多播可以跨不同网络,只要是加入多播组就能接收数据。而广播只能向同一网络中的主机传输数据。
广播也基于UDP完成。直接广播和本地广播,区别在于IP地址:直接广播的IP地址除了网络地址外,其余主机地址全部设置为1;本地广播中使用的IP地址限定为255.255.255.255。数据通信中使用的IP地址是用UDP示例的唯一区别。默认的生成的套接字会阻止广播,因此,需要改变默认设置:
int send_sock;
int bcast = 1; // 对变量进行初始化以将SO_BROADCAST选项信息改为1
...
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
...
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void*)& bcast, sizeof(bcast));
...
只需更改Sender中的套接字选项,Receiver的实现不需要该过程。
发送端:
[root@VM_0_10_centos Broadcast]# cat news_sender_brd.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define BUF_SIZE 30
void error_handling(char * message);
int main(int argc, char * argv[]){
int send_sock;
struct sockaddr_in broad_adr;
FILE * fp;
char buf[BUF_SIZE];
int so_brd = 1;
if(argc != 3){
printf("Usage : %s <Broadcast IP> <PORT>n",argv[0]);
exit(1);
}
send_sock = socket(PF_INET, SOCK_DGRAM, 0);
memset(&broad_adr, 0, sizeof(broad_adr));
broad_adr.sin_family = AF_INET;
broad_adr.sin_addr.s_addr = inet_addr(argv[1]);//broadcast IP
broad_adr.sin_port = htons(atoi(argv[2]));//broadcast port
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void*)&so_brd, sizeof(so_brd));
if((fp = fopen("news.txt","r")) == NULL){
error_handling("fopen() error");
}
while(!feof(fp)){
fgets(buf, BUF_SIZE, fp);
sendto(send_sock, buf, strlen(buf), 0, (struct sockaddr*)&broad_adr, sizeof(broad_adr));
sleep(2);
}
fclose(fp);
close(send_sock);
return 0;
}
void error_handling(char *message){
fputs(message, stderr);
fputc('n',stderr);
exit(1);
}
接收端:
[root@VM_0_10_centos Broadcast]# cat news_receiver_brd.c
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
#define BUF_SIZE 30
void error_handling(char * message);
int main(int argc, char* argv[]){
int recv_sock;
int str_len;
char buf[BUF_SIZE];
struct sockaddr_in adr;
if(argc != 2){
printf("Usage: %s <PORT> n",argv[0]);
exit(1);
}
recv_sock = socket(PF_INET, SOCK_DGRAM, 0);
memset(&adr, 0, sizeof(adr));
adr.sin_family = AF_INET;
adr.sin_addr.s_addr = htonl(INADDR_ANY);
adr.sin_port = htons(atoi(argv[1]));
if(bind(recv_sock, (struct sockaddr*)&adr, sizeof(adr)) == -1){
error_handling("bind() error!");
}
while(1){
str_len = recvfrom(recv_sock, buf, BUF_SIZE-1, 0, NULL, 0);
if(str_len < 0){
break;
}
buf[str_len] = 0;
fputs(buf,stdout);
}
close(recv_sock);
return 0;
}
void error_handling(char* message){
fputs(message,stderr);
fputc('n',stderr);
exit(1);
}
运行结果:
[root@VM_0_10_centos Broadcast]# ./breceiver 9190 &
[1] 32470
[root@VM_0_10_centos Broadcast]# ./bsender 255.255.255.255 9190
this is a broadcast test!
this is a broadcast test!
课后题:
(1)TTL的含义是什么?请从路由器的角度说明较大的TTL值与较小的TTL值之间的区别及问题
TTL是Time to Live的缩写,是决定“信息传递距离”的主要因素。TTL为整数,每经过一个路由器就减1。如果该值为0,该数据报就会因无法再传递而被销毁。TTL设置大了会对网络流量造成不良影响,设置太小的话,就可能无法到达目的地
(2)多播和广播的异同是什么?请从数据通信的角度进行说明
多播和广播的相同点是,两者都是以UDP形式传输数据。一次传输数据,可以向两个以上主机传送数据。但传送的范围是不同的:广播是对局域网的广播;而多播是对网络注册机器的多播
(4)多播也对网络流量有利,请比较TCP数据交换方式解释其原因。
多播数据在路由器进行复制。因此,即使主机数量很多,如果各主机存在的相同路径,也可以通过一次数据传输到多台主机上。但TCP无论路径如何,都要根据主机数量进行数据传输。
(5)多播方式的数据通信需要MBone虚拟网络。换言之,MBone是用于多播的网络,但它是虚拟网络。请解释此处“虚拟网络”。
以物理网络为基础,通过软件方法实现的多播通信必备的虚拟网络
最后
以上就是刻苦芹菜为你收集整理的《TCP IP网络编程》第十四章 多播与广播第十四章 多播与广播的全部内容,希望文章能够帮你解决《TCP IP网络编程》第十四章 多播与广播第十四章 多播与广播所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复