我是靠谱客的博主 刻苦芹菜,最近开发中收集的这篇文章主要介绍《TCP IP网络编程》第十四章 多播与广播第十四章 多播与广播,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

第十四章 多播与广播

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网络编程》第十四章 多播与广播第十四章 多播与广播所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(34)

评论列表共有 0 条评论

立即
投稿
返回
顶部