Python實現PING命令的示例代碼
一、PING簡介
PING(Packet Internet Grope),也稱因特網包探索器。PING使用ICMP回送(ECHO)請求和回送(ECHO)應答報文,一般用于測試網絡連通性,統計往返時間、丟包率等。PING UNIX命令格式如下:
ping [ - Rdfnqrv ] [ - c count ] [ - i wait ] [ - l preload ] [ - p pattern ] [ - s packetsize ] host
如果目標主機正在運行并連在網絡上,它就會對ICMP ECHO請求報文進行應答。每個ICMP ECHO請求報文包含一個IP和ICMP報文收不,后緊跟一個timeval結構,以及用來填充這個報文的填充字節(jié)。
缺省情況下,PING連續(xù)發(fā)送ICMP ECHO請求報文,直到收到中斷信號(Ctrl - C)。PING命令每秒發(fā)送一個報文,并且在程序結束是顯示一個簡要總結。PING命令在程序超時或接收到中斷信號時結束。host參數可以是有效的主機名或IP地址。
報文結構如下:
二、代碼實現
# encoding:utf-8 import time import struct import socket import select def chesksum(data): n = len(data) m = n % 2 sum = 0 for i in range(0, n - m ,2): sum += (data[i]) + ((data[i+1]) << 8)#傳入data以每兩個字節(jié)(十六進制)通過ord轉十進制,第一字節(jié)在低位,第二個字節(jié)在高位 if m: sum += (data[-1]) #將高于16位與低16位相加 sum = (sum >> 16) + (sum & 0xffff) sum += (sum >> 16) #如果還有高于16位,將繼續(xù)與低16位相加 answer = ~sum & 0xffff # 主機字節(jié)序轉網絡字節(jié)序列(參考小端序轉大端序) answer = answer >> 8 | (answer << 8 & 0xff00) return answer def request_ping(data_type,data_code,data_checksum,data_ID,data_Sequence,payload_body): # 把字節(jié)打包成二進制數據 icmp_packet = struct.pack('>BBHHH32s',data_type,data_code,data_checksum,data_ID,data_Sequence,payload_body) icmp_chesksum = chesksum(icmp_packet) #獲取校驗和 # 把校驗和傳入,再次打包 icmp_packet = struct.pack('>BBHHH32s',data_type,data_code,icmp_chesksum,data_ID,data_Sequence,payload_body) return icmp_packet def raw_socket(dst_addr,icmp_packet): ''' 連接套接字,并將數據發(fā)送到套接字 ''' #實例化一個socket對象,ipv4,原套接字,分配協議端口 rawsocket = socket.socket(socket.AF_INET,socket.SOCK_RAW,socket.getprotobyname("icmp")) #記錄當前請求時間 send_request_ping_time = time.time() #發(fā)送數據到網絡 rawsocket.sendto(icmp_packet,(dst_addr,80)) #返回數據 return send_request_ping_time,rawsocket,dst_addr def reply_ping(send_request_ping_time,rawsocket,data_Sequence,timeout = 2): while True: #開始時間 started_select = time.time() #實例化select對象,可讀rawsocket,可寫為空,可執(zhí)行為空,超時時間 what_ready = select.select([rawsocket], [], [], timeout) #等待時間 wait_for_time = (time.time() - started_select) #沒有返回可讀的內容,判斷超時 if what_ready[0] == []: # Timeout return -1 #記錄接收時間 time_received = time.time() #設置接收的包的字節(jié)為1024 received_packet, addr = rawsocket.recvfrom(1024) #獲取接收包的icmp頭 #print(icmpHeader) icmpHeader = received_packet[20:28] #反轉編碼 type, code, checksum, packet_id, sequence = struct.unpack( ">BBHHH", icmpHeader ) if type == 0 and sequence == data_Sequence: return time_received - send_request_ping_time #數據包的超時時間判斷 timeout = timeout - wait_for_time if timeout <= 0: return -1 def dealtime(dst_addr,sumtime,shorttime,longtime,accept,i,time): sumtime += time print(sumtime) if i == 4: print("{0}的Ping統計信息:".format(dst_addr)) print("數據包:已發(fā)送={0},接收={1},丟失={2}({3}%丟失),\n往返行程的估計時間(以毫秒為單位):\n\t最短={4}ms,最長={5}ms,平均={6}ms".format(i+1,accept,i+1-accept,(i+1-accept)/(i+1)*100,shorttime,longtime,sumtime)) def ping(host): send, accept, lost = 0, 0, 0 sumtime, shorttime, longtime, avgtime = 0, 1000, 0, 0 #TODO icmp數據包的構建 data_type = 8 # ICMP Echo Request data_code = 0 # must be zero data_checksum = 0 # "...with value 0 substituted for this field..." data_ID = 0 #Identifier data_Sequence = 1 #Sequence number payload_body = b'abcdefghijklmnopqrstuvwabcdefghi' #data # 將主機名轉ipv4地址格式,返回以ipv4地址格式的字符串,如果主機名稱是ipv4地址,則它將保持不變 dst_addr = socket.gethostbyname(host) print("正在 Ping {0} [{1}] 具有 32 字節(jié)的數據:".format(host,dst_addr)) for i in range(0,4): send = i + 1 #請求ping數據包的二進制轉換 icmp_packet = request_ping(data_type,data_code,data_checksum,data_ID,data_Sequence + i,payload_body) #連接套接字,并將數據發(fā)送到套接字 send_request_ping_time,rawsocket,addr = raw_socket(dst_addr,icmp_packet) #數據包傳輸時間 times = reply_ping(send_request_ping_time,rawsocket,data_Sequence + i) if times > 0: print("來自 {0} 的回復: 字節(jié)=32 時間={1}ms".format(addr,int(times*1000))) accept += 1 return_time = int(times * 1000) sumtime += return_time if return_time > longtime: longtime = return_time if return_time < shorttime: shorttime = return_time time.sleep(0.7) else: lost += 1 print("請求超時。") if send == 4: print("{0}的Ping統計信息:".format(dst_addr)) print("\t數據包:已發(fā)送={0},接收={1},丟失={2}({3}%丟失),\n往返行程的估計時間(以毫秒為單位):\n\t最短={4}ms,最長={5}ms,平均={6}ms".format( i + 1, accept, i + 1 - accept, (i + 1 - accept) / (i + 1) * 100, shorttime, longtime, sumtime/send)) if __name__ == "__main__": i = input("請輸入要ping的主機或域名\n") ping(i)
三、結果顯示
D:\Miniconda3\python.exe D:/網絡協議分析與設計/實驗/ping/ping.py
請輸入要ping的主機或域名
www.baidu.com
正在 Ping www.baidu.com [14.215.177.39] 具有 32 字節(jié)的數據:
來自 14.215.177.39 的回復: 字節(jié)=32 時間=34ms
來自 14.215.177.39 的回復: 字節(jié)=32 時間=26ms
來自 14.215.177.39 的回復: 字節(jié)=32 時間=32ms
來自 14.215.177.39 的回復: 字節(jié)=32 時間=28ms
14.215.177.39的Ping統計信息:
數據包:已發(fā)送=4,接收=4,丟失=0(0.0%丟失),
往返行程的估計時間(以毫秒為單位):
最短=26ms,最長=34ms,平均=30.0ms
Process finished with exit code 0
到此這篇關于Python實現PING命令的示例代碼的文章就介紹到這了,更多相關Python PING命令內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
python+selenium+chromedriver實現爬蟲示例代碼
這篇文章主要介紹了python+selenium+chromedriver實現爬蟲示例代碼,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-04-04python用pd.read_csv()方法來讀取csv文件的實現
本文主要介紹了python用pd.read_csv()方法來讀取csv文件的實現,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2022-06-06