windows7 python 指定源组播 10049_Python3组播通信编程实现教程(发送者+接收者)
一、说明
1.1 标准组播解释
通信分为单播、多播(即组播)、广播三种方式
单播指发送者发送之后,IP数据包被路由器发往目的IP指定的唯一一台设备的通信形式,比如你现在与web服务器通信就是单播形式
广播指发送者发送之后,IP数据包被路由器发给与其连接的所有设备的通信形式
组播指发送者发送之后,IP数据包被路由器发往目的IP对应组播组名下所有主机的通信形式
1.2 个人理解组播解释
对于标准的组播解释,说明似乎还算是清楚的,但具体到技术就有很多问题。比如我将数据包发往一个组播地址,这个组播地址对应一台物理设备吗?如果不是一台物理设备那谁依据什么向哪些主机发送该数据包等等。
结合各资料和自己测试的情况总结出了以下几点:
1) 编写发送程序:组播数据包是且只是目的IP是组播保留地址的UDP数据包,与正常UDP数据包的区别只是其目的IP是组播保留IP
2) 发送数据包主机:网卡在看到目的IP是组播保留IP后,自动将目的mac地址改成组播mac地址然后向其各端口都发送出去
3) 交换机:交换机在接收到数据包之后,通过目的mac地址认识到这是一个组播数据包,修改源mac为自己mac、保持目的mac为组播mac不变向其各端口都发送出去(交换机对组播包的处理和广播包应该是一样的,或者说对于交换机只有单播包和广播包)
4) 路由器:路由器在接收到数据包之后,通过目的mac地址或目的ip地址认识到这是一个组播数据包,修改源mac为自己mac、保持目的mac为组播mac不变,保持源IP不变、保持目的IP为组播保留IP不变,依照与路由表类似的“组播组地址表”向与目的IP匹配的一个或多端口将数据包发送出去
5) 接收数据包主机:接收数据包主机要想接收到发送主机发送的数据包,首先他要(向路由器说明)加入发送者发往的组播组,然后他要在本地启动一个进程监听发送者发往的端口
6) 组播需要硬件支持,有些路由器是不支持组播的,就直观感受看如果在全球实现组播那维护“组播组地址表”会给路由器带来很大负担路由大厂商应该也不是很愿意支持组播;也就是说理论上组播可以在广域网上实现,但其实一般只在局域网中(能够)使用。
7) 注意从本质上而言,接收组播数据包的主机只是启了一个UDP监听,他本身并不能识别是组播发过来的数据包还是直接发过来的数据包(除非对收到的数据包的目的IP是否为组播IP进行判断,但获取目的IP是件很麻烦的事)。也就是说该监听不只是可以接收组播数据包,任何其他如果主机直接向该监听的端口发送UDP数据包该主机也是可以接收到的(已确认过)。
假设使用组播地址为239.255.255.252,使用组播端口为23456,通信举例如下:
发送者S----发送者向239.255.255.252:23456发送一个UDP数据包Packet1
接收者R1(假设其IP地址为134.192.1.100)----第一步启动进程监听239.255.255.252:23456;第二步通过setsockopt加入组播组(239.255.255.252)
接收者R2(假设其IP地址为134.192.1.101)----第一步启动进程监听239.255.255.252:23456;第二步通过setsockopt加入组播组(239.255.255.252)
最终效果----发送者发往239.255.255.252:23456的udp数据包,R1的23456端口收到一份Packet1,R2的23456端口收到一份Packet1
1.3 谁是服务端引发的混乱
我在前面一直使用“发送者”、“接收者”,而没有使用“服务端”、“客户端”,因为“服务端”和“客户端”在组播中容易引发混乱。
在我们一般的socket编程中都是服务端去bind;但在组播中是反过来,客户端(接收者)去bind,而发送者(服务端)是不用去bind的(注意是不用而不是不能,你非要bind也是可以的,bind和不bind只是使用固定端口还是使用随机端口的区别)。
有些小伙伴意识到了这个问题,为了与习惯一致,所以直接将发送者称为客户端,接收者称为服务端。
其实这种叫法是不合适的,以初高中常见的电脑课场景为例:老师控制所有电脑显示老师的电脑操作,这时作为发送者的老师电脑从认知上确实应该是服务端而不是客户端才对。
如果你读了半天没听懂这里在说什么,那不必在意,记得组播中尽里使用“发送者”和“接收者”,少用“服务端”和“客户端”就对了。
1.4 监听组播地址与监听本地地址的区别讨论
在一般的关于组播的文章中,接收者设置的监听地址都是本地地址(如134.192.1.100:23456);但在前面1.2中我们要求接收者R1和R2监听的不是本地地址,而是组播地址239.255.255.252:23456。这是为什么呢?
首先说,这两种监听形式都可以接收到发往239.255.255.252:23456的组播数据包。他们之间的区别是,监听239.255.255.252:23456地址能且只能接收发往239.255.255.252:23456的数据包,而监听134.192.1.100:23456除了能接收发往239.255.255.252:23456的数据包外还能接收直接发往134.192.1.100:23456的数据包。
这样造成的安全区别是,假如接收者实现了这么一项功能:接收到一个打开telnet的命令就直接开启本机的telnet服务。如果监听的是239.255.255.252:23456那么攻击者只有通过局域网内主机发出组播数据包才能打开telnet,但如果监听的是134.192.1.100:23456那么攻击者可以远程直接向134.192.1.100:23456发送数据包开启telnet。
linux上可以通过SO_BINDTODEVICE选项绑定网卡然后设置监听组播地址,但Windows没有实现SO_BINDTODEVICE暂时也不知道如何实现类似功能,所以在下边代码中我也只是linux系统设置了监听组播地址其他系统仍只是监听本地地址。
二、程序实现
2.1 程序代码
发送者代码:
importtimeimportsocket#组播组IP和端口
mcast_group_ip = '239.255.255.252'mcast_group_port= 23456
defsender():#建立发送socket,和正常UDP数据包没区别
send_sock =socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)#每十秒发送一遍消息
whileTrue:
message= "this message send via mcast !"
#发送写法和正常UDP数据包的还是完全没区别
#猜测只可能是网卡自己在识别到目的ip是组播地址后,自动将目的mac地址设为多播mac地址
send_sock.sendto(message.encode(), (mcast_group_ip, mcast_group_port))print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: message send finish')
time.sleep(10)if __name__ == "__main__":
sender()
接收者代码:
importsysimportstructimporttimeimportsocket#linux能绑定网卡这里绑定组播IP地址不会服错,windows没法绑定网卡这里不能绑定组播IP地址只能绑定本网卡IP地址
if "linux" insys.platform:#绑定到的网卡名,如果自己的不是eth0则注意修改
nic_name = "eth0"
#监听的组播地址
mcast_group_ip = "239.255.255.252"
else:
mcast_group_ip=socket.gethostbyname(socket.gethostname())
mcast_group_port= 23456
defreceiver():#建立接收socket,和正常UDP数据包没区别
sock =socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)#25是linux上的socket.SO_BINDTODEVICE的宏定义,但由于windows没实现SO_BINDTODEVICE,所以python索性也就没有实现SO_BINDTODEVICE,我们直接使用25
#windows没有实现SO_BINDTODEVICE,所以不能通过这种方式绑定网卡,windows怎么实现绑定网卡暂不清楚
if "linux" insys.platform:
sock.setsockopt(socket.SOL_SOCKET,25, nic_name)#linux能绑定网卡这里绑定组播IP地址不会服错,windows没法绑定网卡这里不能绑定组播IP地址只能绑定本网卡IP地址
sock.bind((mcast_group_ip, mcast_group_port))#加入组播组
mreq = struct.pack("=4sl", socket.inet_aton(mcast_group_ip), socket.INADDR_ANY)
sock.setsockopt(socket.IPPROTO_IP,socket.IP_ADD_MEMBERSHIP,mreq)#允许端口复用,看到很多教程都有没想清楚意义是什么,我这里直接注释掉
#sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
#设置非阻塞,看到很多教程都有也没想清楚有什么用,我这里直接注释掉
#sock.setblocking(0)
whileTrue:try:
message, addr= sock.recvfrom(1024)print(f'{time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())}: Receive data from {addr}: {message.decode()}')except:print("while receive message error occur")if __name__ == "__main__":
receiver()
2.2 运行截图
发送者截图:
接收者运行截图:
参考:
windows7 python 指定源组播 10049_Python3组播通信编程实现教程(发送者+接收者)相关推荐
- windows7 python 指定源组播 10049_Windows Python多播上的错误10049
这是一些用于设置多播接收器的 Python代码.它在mac和linux上运行良好. import socket,struct ADDR='239.239.250.1' PORT=8001 sock = ...
- windows7 python 指定源组播 10049_试图绑定到特定的外部ip :: [Errno 10049]请求的地址在其上下文中无效无法打开socket-(python 2.7)...
socket.INADDR_ANY 等于 socket.bind('0.0.0.0') 如果绑定到"0.0.0.0"可以监听所有接口(可用) Moxa TCP示例: import ...
- python socket编程 ws2tcpip_Python3组播通信编程实现教程(发送者+接收者)
一.说明 1.1 标准组播解释 通信分为单播.多播(即组播).广播三种方式 单播指发送者发送之后,IP数据包被路由器发往目的IP指定的唯一一台设备的通信形式,比如你现在与web服务器通信就是单播形式 ...
- IP组播之组播路由算法
上一篇文章说的是组管理协议IGMP,它是用来给组播路由器确定自己局域网下面有哪些主机加入了哪些组播的.那么这篇文章就说说IP组播另一个重要协议,组播路由协议.组播路由协议用于在路由器之间共享组信息,为 ...
- 组播源不一定属于组播组,它向组播组发送数据,自己不一定是接收者。可以同时有多个...
组播方式传输信息 综上所述,单播方式适合用户稀少的网络,而广播方式适合用户稠密的网络,当网络中需要某信息的用户量不确定时,单播和广播方式效率很低. IP组播技术的出现及时解决了这个问题.当网络中的某些 ...
- 同一个ip能否两次加入组播_组播IGMPv1/v2/v3精华知识汇总
闲言少叙,直奔主题,开说之前先做点铺垫,回顾一下网络的基础知识. D类地址划分回顾 组播是IPv4地址分类中的D类,我们回顾一下IPv4的地址划分 A类:首bit=0,0-127网段,网络掩码8,其中 ...
- 单播 广播 组播_组播概念3
一.IGMP Message 1.组成员一旦开启IGMP,会自动发送Membership Report消息到叶路由器 2.IGMPv2版本,组成员退出组会发送leave消息,IGMPv1不会 3.也就 ...
- 交换机组播协议-二层组播/三层组播总结
一.组播介绍: 组播技术解决的是以最小的网络开销实现单点发送,多点接收的问题.就实现点对多点数据传输问题,比广播/单播传输更高效,更能节省网络带宽,降低网络负载. 当ip网络中某Rx主机需要接收信息时 ...
- LInux习题练习-04(yum源、用户和组、文件权限、find)
习题练习-04 yum 练习题 用户和组练习题 文件权限练习题 其他练习题 习题练习-04 yum 练习题 利用 yum 安装tree 工具包与http 服务 在web服务初期,由于经常编辑Apach ...
最新文章
- layout折叠后显示标题
- CentOS-6.4-i386硬盘安装
- OnnxRuntime 性能调优
- antd Table/ProList中rowClassName用法(补充记录)
- 11-Docker Bridge详解
- 用HTML,CSS和JavaScript创建iPhone/iPad应用程序
- Safe handle has been closed异常的原因及解决思路
- 在wamp集成环境中添加mysql操作记录
- minkowski sum matlab,Matlab 聚类分析
- 远程给Linux系统更新安装RTX2080ti显卡驱动
- ios 技术支持网址(URL)
- 简单教学 apache 配置 Expire/Cache-Control 头
- Android解析XML的三种方式
- 自学SQL网习题答案
- 布尔教育_燕十八 php,布尔教育_燕十八_HTML视频资源课件
- dubbo服务注册ip地址不正确,rpc服务调用失败?
- 群体遗传学-选择清除分析基本概念及参数
- 在vue框架下element-ui两种引用阿里云图标库的方法
- 复现个有趣的算法:铅笔素描画自动生成
- VMware安装CentOS7超详细版
热门文章
- Dede更新提示DedeTag Engine Create File False的解决办法
- Nginx 反向代理+高可用
- 每个努力奋斗过的人,被不公正的际遇砸了满头包的时候,都有那么一瞬间的代入感。出生就是hard模式的人,早已经历了太多的劳其筋骨饿其体肤,再多的人为考验只会摧毁人对美好的向往。...
- 【SpringCloud】Netflix源码解析之Ribbon:负载均衡策略的定义和实现
- css在盒子中垂直居中和固定居中
- 2015毕业找工作纪实|一年的蜕变毕业生
- root 链接ftp
- 线程同步-事件内核对象
- python作业代码没有缩进严重吗_Python代码需要缩进吗
- 调用图片文件夹中的任意图片随机显示_他来了,他来了,Mathpix拜拜了~~~文字、表格、公式图片识别神器V0.1测试版...