原文作者:aircraft

原文链接:https://www.cnblogs.com/DOMLX/p/9614288.html

本网络编程入门系列博客是连载学习的,有兴趣的可以看我博客其他篇。。。。c++ 网络编程课设入门超详细教程 ---目录

一.多播

锲子:有这么一种情况,网络电台可能需要同时向成千上万的用户传输相同的数据,如果用我们以前讲过的传输形式,每个用户都传输一次,这样肯定是不合理的。因此,就引入了多播技术来解决这个问题,它可以同时向大量用户发送相同数据。其基本原理是这样的:有个多播组,只要加入这个组里的所有客服端,服务端发送的数据它们都能收到,具体传输到多播组里的每个客户是由路由完成的(如果路由器不支持多播或网络堵塞,实现多播也会使用隧道技术)

    • 多播的数据传输特点如下:
      1,多播服务器端针对特定多播组,只需发送1次数据,该组内的所有所有客服端都能接收数据。
      2,多播组数可在IP地址范围内任意增加。

    • 设置生存时间和加入多播组的方法
      1,设置生存时间:只指服务端发送的数据包最远能传递的距离,用整数表示,并且每经过1个路由器就减1,当为0时,该数据包无法再被传递,只能销毁。因此,这个值设置过大将影响网络流量。当然,设置过小也会无法传递到目标(通过套接字可选项设置,示例代码中有使用方法)。

      2,加入多播组:也是通过套接字可选项设置,示例代码中有使用方法,这里只介绍多播组的结构体ip_mreq。

    • struct ip_mreq
      {
      struct in_addr imr_multiaddr; //多播组的IP地址
      struct in_addr imr_interface; //加入的客服端主机IP地址

      }

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h> #define TTL 64 //数据包生存时间,即最多可以传递经过第64个路由时销毁
#define BUF_SIZE 30
void error_handling(char *message); int main(int argc, const char * argv[]) {
int send_sock;
struct sockaddr_in mul_adr;
int time_live = TTL;
FILE *fp;
char buf[BUF_SIZE];
if (argc != ) {
printf("Usage : %s <GroupIp> <Port> \n", argv[]);
exit();
} //基于UDP的多播
send_sock = socket(PF_INET, SOCK_DGRAM, );
memset(&mul_adr, , sizeof(mul_adr));
mul_adr.sin_family = AF_INET;
mul_adr.sin_addr.s_addr = inet_addr(argv[]);
mul_adr.sin_port = htons(atoi(argv[])); //设置生存时间(除了这里其它基本和UDP编写一样)
setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&time_live, sizeof(time_live)); if((fp = fopen("/Users/app05/Desktop/test.txt", "r")) == NULL)
error_handling("fopen() error"); while (!feof(fp)) //如果文件结束,则返回非0值,否则返回0
{
fgets(buf, BUF_SIZE, fp);
sendto(send_sock, buf, strlen(buf), , (struct sockaddr *)&mul_adr, sizeof(mul_adr));
sleep(); //只是为了加个传输数据时间间隔,没有特殊意义
} fclose(fp);
close(send_sock);
return ;
} void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit();
}

接收者(receiver):

#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, const char * argv[]) {
int recv_sock;
int str_len;
char buf[BUF_SIZE];
struct sockaddr_in adr;
struct ip_mreq join_adr; //多播组结构体 if(argc != )
{
printf("Usage : %s <GroupIp> <Port> \n", argv[]);
exit();
} recv_sock = socket(PF_INET, SOCK_DGRAM, );
memset(&adr, , sizeof(adr));
adr.sin_family = AF_INET;
adr.sin_addr.s_addr = htonl(INADDR_ANY);
adr.sin_port = htons(atoi(argv[])); if(bind(recv_sock, (struct sockaddr *)&adr, sizeof(adr)) == -)
error_handling("bind() error"); //加入多播组
join_adr.imr_multiaddr.s_addr = inet_addr(argv[]);
join_adr.imr_interface.s_addr = htonl(INADDR_ANY);
setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&join_adr, sizeof(join_adr)); while () {
str_len = recvfrom(recv_sock, buf, BUF_SIZE - , , NULL, );//只需要多播组IP地址,不关心自己主机地址
if(str_len < )
break;
buf[str_len] = ;
fputs(buf, stdout);
} close(recv_sock);
return ;
} void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit();
}

二.广播

广播在功能上和多播是一样的,都是同时可以向大量客户传递数据。但他们在网络范围上有区别,多播可以跨越不同的网络,只要加入了多播组就能接收数据。但广播只能向同一网络中的主机传输数据。
广播分为:直接广播与本地广播,直接广播sender的IP地址只需指定网络地址,主机地址全部填255。这样处在这个网络地址里的所有主机就可以接收数据了。而本地广播sender的IP地址写255.255.255.255,这样本地网络所有主机就可以接收数据了。

//将SO_BROADCAST可选项设置为1就表示开启了套接字广播功能,默认是关闭的。
int bcast = 1;
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void *) &bcast, sizeof(bcast));

下面就多播的代码示例稍作修改,本地广播的示例如下:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h> #define TTL 64 //数据包生存时间,即最多可以传递经过第64个路由时销毁
#define BUF_SIZE 30
void error_handling(char *message); int main(int argc, const char * argv[]) {
int send_sock;
struct sockaddr_in mul_adr;
int time_live = TTL;
FILE *fp;
char buf[BUF_SIZE];
if (argc != ) {
printf("Usage : %s <GroupIp> <Port> \n", argv[]);
exit();
} //基于UDP的多播
send_sock = socket(PF_INET, SOCK_DGRAM, );
memset(&mul_adr, , sizeof(mul_adr));
mul_adr.sin_family = AF_INET;
mul_adr.sin_addr.s_addr = inet_addr(argv[]);
mul_adr.sin_port = htons(atoi(argv[])); //设置生存时间(除了这里其它基本和UDP编写一样)
//setsockopt(send_sock, IPPROTO_IP, IP_MULTICAST_TTL, (void *)&time_live, sizeof(time_live)); /*add:广播修改处*/
//默认套接字是关闭广播的,开启如下:
int so_brd = ; //设置为1就可以开启广播
setsockopt(send_sock, SOL_SOCKET, SO_BROADCAST, (void *)&so_brd, sizeof(so_brd)); if((fp = fopen("/Users/app05/Desktop/test.txt", "r")) == NULL)
error_handling("fopen() error"); while (!feof(fp)) //如果文件结束,则返回非0值,否则返回0
{
fgets(buf, BUF_SIZE, fp);
sendto(send_sock, buf, strlen(buf), , (struct sockaddr *)&mul_adr, sizeof(mul_adr));
sleep(); //只是为了加个传输数据时间间隔,没有特殊意义
} fclose(fp);
close(send_sock);
return ;
} void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit();
}

另一个修改:

#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, const char * argv[]) {
int recv_sock;
int str_len;
char buf[BUF_SIZE];
struct sockaddr_in adr;
//struct ip_mreq join_adr; //多播组结构体 if(argc != )
{
printf("Usage : %s <GroupIp> <Port> \n", argv[]);
exit();
} recv_sock = socket(PF_INET, SOCK_DGRAM, );
memset(&adr, , sizeof(adr));
adr.sin_family = AF_INET;
adr.sin_addr.s_addr = htonl(INADDR_ANY);
adr.sin_port = htons(atoi(argv[])); if(bind(recv_sock, (struct sockaddr *)&adr, sizeof(adr)) == -)
error_handling("bind() error"); //加入多播组
//join_adr.imr_multiaddr.s_addr = inet_addr(argv[1]);
//join_adr.imr_interface.s_addr = htonl(INADDR_ANY);
//setsockopt(recv_sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (void *)&join_adr, sizeof(join_adr)); while () {
str_len = recvfrom(recv_sock, buf, BUF_SIZE - , , NULL, );//只需要多播组IP地址,不关心自己主机地址
if(str_len < )
break;
buf[str_len] = ;
fputs(buf, stdout);
} close(recv_sock);
return ;
} void error_handling(char *message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit();
}

三.多播与广播的区别

  • 多播:“多播”也可以称为“组播”,在网络技术的应用并不是很多,网上视频会议、网上视频点播特别适合采用多播方式。因为如果采用单播方式,逐个节点传输,有多少个目标节点,就会有多少次传送过程,这种方式显然效率极低,是不可取的;如果采用不区分目标、全部发送的广播方式,虽然一次可以传送完数据,但是显然达不到区分特定数据接收对象的目的。采用多播方式,既可以实现一次传送所有目标节点的数据,也可以达到只对特定对象传送数据的目的。   IP网络的多播一般通过多播IP地址来实现。多播IP地址就是D类IP地址,即224.0.0.0至239.255.255.255之间的IP地址。Windows 2000中的DHCP管理器支持多播IP地址的自动分配。
  • 广播:“广播”在网络中的应用较多,如客户机通过DHCP自动获得IP地址的过程就是通过广播来实现的。但是同单播和多播相比,广播几乎占用了子网内网络的所有带宽。拿开会打一个比方吧,在会场上只能有一个人发言,想象一下如果所有的人同时都用麦克风发言,那会场上就会乱成一锅粥。集线器由于其工作原理决定了不可能过滤广播风暴,一般的交换机也没有这一功能,不过现在有的网络交换机(如全向的QS系列交换机)也有过滤广播风暴功能了,路由器本身就有隔离广播风暴的作用。   广播风暴不能完全杜绝,但是只能在同一子网内传播,就好像喇叭的声音只能在同一会场内传播一样,因此在由几百台甚至上千台电脑构成的大中型局域网中,一般进行子网划分,就像将一个大厅用墙壁隔离成许多小厅一样,以达到隔离广播风暴的目的。   在IP网络中,广播地址用IP地址“255.255.255.255”来表示,这个IP地址代表同一子网内所有的IP地址。

     
     
     
  • 最后说一句啦。本网络编程入门系列博客是连载学习的,有兴趣的可以看我博客其他篇。。。。c++ 网络编程课设入门超详细教程 ---目录

    好了今天对网络编程的学习就到这里结束了,小飞机我要撤了去吃饭了。,,,很多人大学都很迷茫不知道学点什么好,,,,,管他的,想那么多干嘛,先学了再说,对技术如有偏见,那么你的领域就局限于此了---《一专多精》

    参考博客:https://blog.csdn.net/u010223072/article/details/48269213

    参考书籍:《TCP/IP 网络编程 --尹圣雨》

  • 若有兴趣交流分享技术,可关注本人公众号,里面会不定期的分享各种编程教程,和共享源码,诸如研究分享关于c/c++,python,前端,后端,opencv,halcon,opengl,机器学习深度学习之类有关于基础编程,图像处理和机器视觉开发的知识

c++ 网络编程(六)LINUX下 socket编程 多播与广播 实现一次发送所有组客户端都能接收到的更多相关文章

  1. Linux下Socket编程的端口问题( Bind error: Address already in use )

    Linux下Socket编程的端口问题( Bind error: Address already in use ) 在进行linux网络编程时,每次修改了源代码并再次编译运行时,常遇到下面的地使用错误 ...

  2. linux下socket编程实例

    linux下socket编程实例一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.s ...

  3. Linux下socket编程基本知识

    本文档主要讲解了Linux下socket编程的一些基本知识,主要包括套接字和字节序的概念,以及一些常用的结构体和函数. 本文是在网易云课堂学习过程中的记录,这个老师讲得很不错,推荐大家围观. Linu ...

  4. LInux下socket编程学习笔记

    1.socket套接字: socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“打开open –> 读写write/read –> 关闭close”模 ...

  5. c++ 网络编程(七) LINUX下 socket编程 基于套接字的标准I/O函数使用 与 fopen,feof,fgets,fputs函数用法

    原文作者:aircraft 原文链接:https://www.cnblogs.com/DOMLX/p/9614820.html 一.标准I/O 1,什么是标准I/O?其实是指C语言里的文件操作函数,如 ...

  6. [转] - linux下socket编程实例

    一.基本socket函数Linux系统是通过提供套接字(socket)来进行网络编程的.网络的socket数据传输是一种特殊的I/O,socket也是一种文件描述符.socket也有一个类似于打开文件 ...

  7. linux下socket编程-进程间通信

    一.什么是Socket Socket接口是TCP/IP网络通信的API,Socket接口定义了许多函数或例程,可以用它们来开发TCP/IP网络上的应用程序. Socket类型有两种:流式Socket ...

  8. linux下socket编程

    相关结构 //下边这两个结构定义在<sys/types.h>里 //一般的地址结构,只能用于覆盖(把其他地址转换为此类型),且只能引用该地址的sa_family字段 struct sock ...

  9. 3、linux下Socket编程-TCP/UDP

    1.什么是Socket 网络的 Socket数据传输是一种特殊的I/O,Socket也是一种文件描述符.Socket也具有一个类似于打开文件的函数调用Socket(),该函数返 回一个整型的Socke ...

随机推荐

  1. Web应用与Spring MVC锁session

    http是无连接的,所以服务器上并不会为每个用户开辟一个线程,因为没有用户这个说法,但是服务器端是有session的,为了防止一个用户同时有多个请求在处理,spring mvc在处理请求时把sessi ...

  2. RAD Studio Demo Code和几个国外FMX网站 good

    FireMonkey X –  Amazing overview of FireMonkey FMX Feeds – All your FireMonkey news in one place FMX ...

  3. Mac安装Tomcat

    1. 到Tomcat官网下载,如下找tar格式文件: http://ftp.twaren.net/Unix/Web/apache/tomcat/tomcat-8/v8.0.41/bin/apache- ...

  4. android之实现底部TabHost

    先说布局文件,如下:利用android:layout_alignParentBottom="true" 实现底部显示 <?xml version="1.0" ...

  5. S.O.L.I.D原则

    SILID原则: 是面向对象编程和设计的重要原则,在我们编程的过程中是谨记的重点,所以对其有深刻了解是必须的.   < Clean Code(代码整洁之道)>作者Robert C. Mar ...

  6. Ray tracing performance benchmark

    accel. avg size 3.14accel. avg depth 16.15accel. max size 8accel. max depth 20accel. GPIT 3.00 MB tr ...

  7. Android通知栏介绍与适配总结(上篇)

    此文已由作者黎星授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 由于历史原因,Android在发布之初对通知栏Notification的设计相当简单,而如今面对各式各样的通知 ...

  8. 适用于Java的嵌入式脚本语言

    此文已由作者赵昕授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. fakescript 轻量级嵌入式脚本语言 https://github.com/esrrhs/fakescr ...

  9. HAOI2010 最长公共子序列

    题目链接:戳我 30分暴力....暴力提取子序列即可qwqwq #include<iostream> #include<cstdio> #include<algorith ...

  10. CentOS下TFTP服务安装

    CentOS下TFTP服务安装 今天和同学做交换机恢复DCN操作系统的任务,然后需要用到tftp,然后就开始研究.这里对TFTP服务进行介绍以及安装. tftp 比 ftp 更易于管理 tftp 比 ...