通過python下的socket實現組播資料的傳送和接收
阿新 • • 發佈:2019-01-29
關於網路組播的解釋我不在此詳述了,想了解的直接百娘就可以了,本人也是新手,研究了幾天Python的組播程式設計後,目前終於成功的解決了自己找的各種麻煩,所以現在總結如下:
python實現socket組播有N種寫法,我現在只給出自己認為比較妥當的寫法。
資料傳送 sender:
import time import struct from socket import * SENDERIP = '192.168.0.116'#本地ip SENDERPORT = 1501#本地介面 MYPORT = 1234#傳送資料到該埠 MYGROUP = '224.1.1.1'#組播組 MYTTL = 255 # 傳送資料的TTL值 def sender(): s = socket(AF_INET, SOCK_DGRAM,IPPROTO_UDP) s.bind((SENDERIP,SENDERPORT)) # Set Time-to-live (optional) ttl_bin = struct.pack('@i', MYTTL) s.setsockopt(IPPROTO_IP, IP_MULTICAST_TTL, ttl_bin) status = s.setsockopt(IPPROTO_IP, IP_ADD_MEMBERSHIP, inet_aton(MYGROUP) + inet_aton(SENDERIP))#加入到組播組 while True: data = 'cisco' s.sendto(data + '\0', (MYGROUP, MYPORT)) print "send data ok !" time.sleep(10) if __name__ == "__main__": sender()
接收資料 receiver:
import time import socket SENDERIP = '192.168.0.116' MYPORT = 1234 MYGROUP = '224.1.1.1' def receiver(): #create a UDP socket sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP) #allow multiple sockets to use the same PORT number sock.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) #Bind to the port that we know will receive multicast data sock.bind((SENDERIP,MYPORT)) #tell the kernel that we are a multicast socket #sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_TTL, 255) #Tell the kernel that we want to add ourselves to a multicast group #The address for the multicast group is the third param status = sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP, socket.inet_aton(MYGROUP) + socket.inet_aton(SENDERIP)); sock.setblocking(0) #ts = time.time() while 1: try: data, addr = sock.recvfrom(1024) except socket.error, e: pass else: print "Receive data!" print "TIME:" , time.time() print "FROM: ", addr print "DATA: ", data if __name__ == "__main__": receiver()
不出意外的話,你按照以上兩個指令碼測試,在windows下是沒有問題。
可以實現的模式有:
windows 發資料 ,windows 接資料
Linux(如:CentOS) 發資料 ,windows 接資料
但是,linux接收資料,就不靈了。反正我試驗好久,也沒能成功。
ps:我親自試驗過,linux下用tcpdump抓包,是可以抓到的。
解決方法:
將receiver指令碼的sock.bind((SENDERIP,MYPORT))(也就是繫結IP)更改為空或者“0.0.0.0”,然後你再試一下,基本上就全都通了。
網上的解釋是,如果繫結為“0.0.0.0”,則表明是所有網絡卡的資料都可以接收到,但是我有點兒糊塗的地方是,我就一個網絡卡,而且只有個IP,難道我接受的資料不是通過這個IP接收到的?怪哉!
如果有大牛知道原因,請告知,謝謝!