日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程语言 > python >内容正文

python

windows7 python 指定源组播 10049_Python3组播通信编程实现教程(发送者+接收者)

發(fā)布時(shí)間:2024/7/23 python 51 豆豆
生活随笔 收集整理的這篇文章主要介紹了 windows7 python 指定源组播 10049_Python3组播通信编程实现教程(发送者+接收者) 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

一、說(shuō)明

1.1 標(biāo)準(zhǔn)組播解釋

通信分為單播、多播(即組播)、廣播三種方式

單播指發(fā)送者發(fā)送之后,IP數(shù)據(jù)包被路由器發(fā)往目的IP指定的唯一一臺(tái)設(shè)備的通信形式,比如你現(xiàn)在與web服務(wù)器通信就是單播形式

廣播指發(fā)送者發(fā)送之后,IP數(shù)據(jù)包被路由器發(fā)給與其連接的所有設(shè)備的通信形式

組播指發(fā)送者發(fā)送之后,IP數(shù)據(jù)包被路由器發(fā)往目的IP對(duì)應(yīng)組播組名下所有主機(jī)的通信形式

1.2 個(gè)人理解組播解釋

對(duì)于標(biāo)準(zhǔn)的組播解釋,說(shuō)明似乎還算是清楚的,但具體到技術(shù)就有很多問(wèn)題。比如我將數(shù)據(jù)包發(fā)往一個(gè)組播地址,這個(gè)組播地址對(duì)應(yīng)一臺(tái)物理設(shè)備嗎?如果不是一臺(tái)物理設(shè)備那誰(shuí)依據(jù)什么向哪些主機(jī)發(fā)送該數(shù)據(jù)包等等。

結(jié)合各資料和自己測(cè)試的情況總結(jié)出了以下幾點(diǎn):

1) 編寫(xiě)發(fā)送程序:組播數(shù)據(jù)包是且只是目的IP是組播保留地址的UDP數(shù)據(jù)包,與正常UDP數(shù)據(jù)包的區(qū)別只是其目的IP是組播保留IP

2) 發(fā)送數(shù)據(jù)包主機(jī):網(wǎng)卡在看到目的IP是組播保留IP后,自動(dòng)將目的mac地址改成組播mac地址然后向其各端口都發(fā)送出去

3) 交換機(jī):交換機(jī)在接收到數(shù)據(jù)包之后,通過(guò)目的mac地址認(rèn)識(shí)到這是一個(gè)組播數(shù)據(jù)包,修改源mac為自己mac、保持目的mac為組播mac不變向其各端口都發(fā)送出去(交換機(jī)對(duì)組播包的處理和廣播包應(yīng)該是一樣的,或者說(shuō)對(duì)于交換機(jī)只有單播包和廣播包)

4) 路由器:路由器在接收到數(shù)據(jù)包之后,通過(guò)目的mac地址或目的ip地址認(rèn)識(shí)到這是一個(gè)組播數(shù)據(jù)包,修改源mac為自己mac、保持目的mac為組播mac不變,保持源IP不變、保持目的IP為組播保留IP不變,依照與路由表類(lèi)似的“組播組地址表”向與目的IP匹配的一個(gè)或多端口將數(shù)據(jù)包發(fā)送出去

5) 接收數(shù)據(jù)包主機(jī):接收數(shù)據(jù)包主機(jī)要想接收到發(fā)送主機(jī)發(fā)送的數(shù)據(jù)包,首先他要(向路由器說(shuō)明)加入發(fā)送者發(fā)往的組播組,然后他要在本地啟動(dòng)一個(gè)進(jìn)程監(jiān)聽(tīng)發(fā)送者發(fā)往的端口

6) 組播需要硬件支持,有些路由器是不支持組播的,就直觀感受看如果在全球?qū)崿F(xiàn)組播那維護(hù)“組播組地址表”會(huì)給路由器帶來(lái)很大負(fù)擔(dān)路由大廠商應(yīng)該也不是很愿意支持組播;也就是說(shuō)理論上組播可以在廣域網(wǎng)上實(shí)現(xiàn),但其實(shí)一般只在局域網(wǎng)中(能夠)使用。

7)? 注意從本質(zhì)上而言,接收組播數(shù)據(jù)包的主機(jī)只是啟了一個(gè)UDP監(jiān)聽(tīng),他本身并不能識(shí)別是組播發(fā)過(guò)來(lái)的數(shù)據(jù)包還是直接發(fā)過(guò)來(lái)的數(shù)據(jù)包(除非對(duì)收到的數(shù)據(jù)包的目的IP是否為組播IP進(jìn)行判斷,但獲取目的IP是件很麻煩的事)。也就是說(shuō)該監(jiān)聽(tīng)不只是可以接收組播數(shù)據(jù)包,任何其他如果主機(jī)直接向該監(jiān)聽(tīng)的端口發(fā)送UDP數(shù)據(jù)包該主機(jī)也是可以接收到的(已確認(rèn)過(guò))。

假設(shè)使用組播地址為239.255.255.252,使用組播端口為23456,通信舉例如下:

發(fā)送者S----發(fā)送者向239.255.255.252:23456發(fā)送一個(gè)UDP數(shù)據(jù)包Packet1

接收者R1(假設(shè)其IP地址為134.192.1.100)----第一步啟動(dòng)進(jìn)程監(jiān)聽(tīng)239.255.255.252:23456;第二步通過(guò)setsockopt加入組播組(239.255.255.252)

接收者R2(假設(shè)其IP地址為134.192.1.101)----第一步啟動(dòng)進(jìn)程監(jiān)聽(tīng)239.255.255.252:23456;第二步通過(guò)setsockopt加入組播組(239.255.255.252)

最終效果----發(fā)送者發(fā)往239.255.255.252:23456的udp數(shù)據(jù)包,R1的23456端口收到一份Packet1,R2的23456端口收到一份Packet1

1.3 誰(shuí)是服務(wù)端引發(fā)的混亂

我在前面一直使用“發(fā)送者”、“接收者”,而沒(méi)有使用“服務(wù)端”、“客戶(hù)端”,因?yàn)椤胺?wù)端”和“客戶(hù)端”在組播中容易引發(fā)混亂。

在我們一般的socket編程中都是服務(wù)端去bind;但在組播中是反過(guò)來(lái),客戶(hù)端(接收者)去bind,而發(fā)送者(服務(wù)端)是不用去bind的(注意是不用而不是不能,你非要bind也是可以的,bind和不bind只是使用固定端口還是使用隨機(jī)端口的區(qū)別)。

有些小伙伴意識(shí)到了這個(gè)問(wèn)題,為了與習(xí)慣一致,所以直接將發(fā)送者稱(chēng)為客戶(hù)端,接收者稱(chēng)為服務(wù)端。

其實(shí)這種叫法是不合適的,以初高中常見(jiàn)的電腦課場(chǎng)景為例:老師控制所有電腦顯示老師的電腦操作,這時(shí)作為發(fā)送者的老師電腦從認(rèn)知上確實(shí)應(yīng)該是服務(wù)端而不是客戶(hù)端才對(duì)。

如果你讀了半天沒(méi)聽(tīng)懂這里在說(shuō)什么,那不必在意,記得組播中盡里使用“發(fā)送者”和“接收者”,少用“服務(wù)端”和“客戶(hù)端”就對(duì)了。

1.4 監(jiān)聽(tīng)組播地址與監(jiān)聽(tīng)本地地址的區(qū)別討論

在一般的關(guān)于組播的文章中,接收者設(shè)置的監(jiān)聽(tīng)地址都是本地地址(如134.192.1.100:23456);但在前面1.2中我們要求接收者R1和R2監(jiān)聽(tīng)的不是本地地址,而是組播地址239.255.255.252:23456。這是為什么呢?

首先說(shuō),這兩種監(jiān)聽(tīng)形式都可以接收到發(fā)往239.255.255.252:23456的組播數(shù)據(jù)包。他們之間的區(qū)別是,監(jiān)聽(tīng)239.255.255.252:23456地址能且只能接收發(fā)往239.255.255.252:23456的數(shù)據(jù)包,而監(jiān)聽(tīng)134.192.1.100:23456除了能接收發(fā)往239.255.255.252:23456的數(shù)據(jù)包外還能接收直接發(fā)往134.192.1.100:23456的數(shù)據(jù)包。

這樣造成的安全區(qū)別是,假如接收者實(shí)現(xiàn)了這么一項(xiàng)功能:接收到一個(gè)打開(kāi)telnet的命令就直接開(kāi)啟本機(jī)的telnet服務(wù)。如果監(jiān)聽(tīng)的是239.255.255.252:23456那么攻擊者只有通過(guò)局域網(wǎng)內(nèi)主機(jī)發(fā)出組播數(shù)據(jù)包才能打開(kāi)telnet,但如果監(jiān)聽(tīng)的是134.192.1.100:23456那么攻擊者可以遠(yuǎn)程直接向134.192.1.100:23456發(fā)送數(shù)據(jù)包開(kāi)啟telnet。

linux上可以通過(guò)SO_BINDTODEVICE選項(xiàng)綁定網(wǎng)卡然后設(shè)置監(jiān)聽(tīng)組播地址,但Windows沒(méi)有實(shí)現(xiàn)SO_BINDTODEVICE暫時(shí)也不知道如何實(shí)現(xiàn)類(lèi)似功能,所以在下邊代碼中我也只是linux系統(tǒng)設(shè)置了監(jiān)聽(tīng)組播地址其他系統(tǒng)仍只是監(jiān)聽(tīng)本地地址。

二、程序?qū)崿F(xiàn)

2.1 程序代碼

發(fā)送者代碼:

importtimeimportsocket#組播組IP和端口

mcast_group_ip = '239.255.255.252'mcast_group_port= 23456

defsender():#建立發(fā)送socket,和正常UDP數(shù)據(jù)包沒(méi)區(qū)別

send_sock =socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)#每十秒發(fā)送一遍消息

whileTrue:

message= "this message send via mcast !"

#發(fā)送寫(xiě)法和正常UDP數(shù)據(jù)包的還是完全沒(méi)區(qū)別

#猜測(cè)只可能是網(wǎng)卡自己在識(shí)別到目的ip是組播地址后,自動(dòng)將目的mac地址設(shè)為多播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能綁定網(wǎng)卡這里綁定組播IP地址不會(huì)服錯(cuò),windows沒(méi)法綁定網(wǎng)卡這里不能綁定組播IP地址只能綁定本網(wǎng)卡IP地址

if "linux" insys.platform:#綁定到的網(wǎng)卡名,如果自己的不是eth0則注意修改

nic_name = "eth0"

#監(jiān)聽(tīng)的組播地址

mcast_group_ip = "239.255.255.252"

else:

mcast_group_ip=socket.gethostbyname(socket.gethostname())

mcast_group_port= 23456

defreceiver():#建立接收socket,和正常UDP數(shù)據(jù)包沒(méi)區(qū)別

sock =socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)#25是linux上的socket.SO_BINDTODEVICE的宏定義,但由于windows沒(méi)實(shí)現(xiàn)SO_BINDTODEVICE,所以python索性也就沒(méi)有實(shí)現(xiàn)SO_BINDTODEVICE,我們直接使用25

#windows沒(méi)有實(shí)現(xiàn)SO_BINDTODEVICE,所以不能通過(guò)這種方式綁定網(wǎng)卡,windows怎么實(shí)現(xiàn)綁定網(wǎng)卡暫不清楚

if "linux" insys.platform:

sock.setsockopt(socket.SOL_SOCKET,25, nic_name)#linux能綁定網(wǎng)卡這里綁定組播IP地址不會(huì)服錯(cuò),windows沒(méi)法綁定網(wǎng)卡這里不能綁定組播IP地址只能綁定本網(wǎng)卡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)#允許端口復(fù)用,看到很多教程都有沒(méi)想清楚意義是什么,我這里直接注釋掉

#sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

#設(shè)置非阻塞,看到很多教程都有也沒(méi)想清楚有什么用,我這里直接注釋掉

#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 運(yùn)行截圖

發(fā)送者截圖:

接收者運(yùn)行截圖:

參考:

總結(jié)

以上是生活随笔為你收集整理的windows7 python 指定源组播 10049_Python3组播通信编程实现教程(发送者+接收者)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。