以前都是透過用C++寫的Client API負責連接Server,UI端再去呼叫dll來用,之前TCL腳本,C#,C++程式都是去呼叫dll,所以一開始Python也是用這種方式連結。而老闆就是覺得這樣太侷限,突發奇想問能不能用純Python方式,不用呼叫dll。結論是當然可以,只是必須整個重寫,而且理論上Client端就能跨平台了。寫出來Python版的API之後,已經丟給TC驗證。
閒暇就在想能不能不透過Socket,直接叫網卡送非TCP/IP標頭的自定包。就像我們公司產品一樣,MAC位址都可以自己訂這樣。在Windows底下,有個Winpcap的玩意可以做到,而Python相對應的就是Winpcapy了。只可惜Winpcapy是封裝Winpcap,用ctype方式去呼叫Winpcap dll,包成Python方式呼叫而已,所以,還是不能跨平台。
Winpcapy下載位置
Winpcapy引用非常簡單,底下宣告,就可以直接用了:
from winpcapy import *Winpcapy範例非常完整,直接把兩個範例(basic_dump和sendpack)合起來改。
先用basic_dump範例的抓取網卡資訊名稱,再當作sendpack裡頭pcap_open_live function的參數。
alldevs=POINTER(pcap_if_t)() errbuf= create_string_buffer(PCAP_ERRBUF_SIZE) ## Retrieve the device list if (pcap_findalldevs(byref(alldevs), errbuf) == -1): print ("Error in pcap_findalldevs: %s\n" % errbuf.value) sys.exit(1) d=alldevs #因為電腦對外網卡腦是第一個,不用判斷next直接抓 d=d.contents #Open the adapter fp = pcap_open_live(d.name,65536,1,1000,errbuf)造一個特定包。這邊只動到MAC
u_char packet[100]; packet[0]=0x00 packet[1]=0x22 packet[2]=0xA2 packet[3]=0x00 packet[4]=0x00 packet[5]=0x01 packet[6]=0x00 packet[7]=0x22 packet[8]=0xA2 packet[9]=0x00 packet[10]=0x00 packet[11]=0x02迴圈送出並計算時間
bmillis = int(round(time.time() * 1000)) ## Send down the packet for i in range(0,1000): if (pcap_sendpacket(fp,packet,100) != 0): print ("\nError sending the packet: %s\n" % pcap_geterr(fp)) sys.exit(3) emillis = int(round(time.time() * 1000)) print "TotalTime(ms) = %d" %(emillis-bmillis)打1000個包時間約217ms,換算大約1秒鐘可以打出包長100 bytes的包4500多個。
以我網卡100Mb網卡速率,最多可以打出(100,000,000/8)/(100+20)=104166個包。換算效率是4500/104166=4.32%。還蠻差的。不過因為使用Winpcap等於用軟體計算crc,Append在包最後面再送出,因此這速度可以了。反正client端我們是用來送控制包,firmware也沒法處理這樣快又多的命令。只是不能拿來收送包測自訂包throughput了。
0 意見:
張貼留言