這兩天在測試IPV6與DNS,晚上查了下資料,寫了個DNS用戶端,其中請求訊息編碼部分參考網上執行個體。
剛完成了編碼,功能還沒有測試。
1、代碼:
#!/usr/bin/env python# -*- coding: utf-8 -*-import ConfigParserimport socketimport time import stringimport osimport reimport structdef dns_codec(hostname): ''' Function:請求訊息編碼 Input:hostname:主機名稱,如www.baidu.com Output: 編碼後的位元組流 author: socrates date:2012-12-14 ''' index = os.urandom(2) hoststr = ''.join(chr(len(x))+x for x in hostname.split('.')) data = '%s\x01\x00\x00\x01\x00\x00\x00\x00\x00\x00%s\x00\x00\x01\x00\x01' % (index, hoststr) data = struct.pack('!H', len(data)) + data return datadef dns_decode(in_sock): ''' Function:響應訊息解碼 Input:in_sock:接收訊息的socket Output:解碼後的內容 author: socrates date:2012-12-14 ''' rfile = in_sock.makefile('rb') size = struct.unpack('!H', rfile.read(2))[0] data = rfile.read(size) iplist = re.findall('\xC0.\x00\x01\x00\x01.{6}(.{4})', data) return ['.'.join(str(ord(x)) for x in s) for s in iplist] def dns_sendmsg(): ''' Function:通過socket發送DNS查詢訊息 Input:None Output:None author: socrates date:2012-12-14 ''' ens_client_config = ConfigParser.ConfigParser() #讀取設定檔 try: ens_client_config.readfp(open('ens_client_config.ini')) except ConfigParser.Error: print 'read ens_client_config.ini failed.' #擷取需要的資訊 server_ip_1 = ens_client_config.get("server_info","ip_1") server_port_1 = ens_client_config.get("server_info","port_1") sockettype_1 = ens_client_config.get("server_info","sockettype_1") heartbeat_1 = ens_client_config.get("server_info","heartbeat_1") msg_1 = ens_client_config.get("server_info","msg_1") #IP類型 address_family = {True:socket.AF_INET6, False:socket.AF_INET}[':' in server_ip_1] #傳輸類型 socket_type = {True:socket.SOCK_STREAM , False:socket.SOCK_DGRAM}['TCP' == sockettype_1.upper()] try: sock = socket.socket(address_family, socket_type) except socket.error, e: print 'create socket return error. errno = %d, errmsg = %s' % (e.args[0], e.args[1]) #串連伺服器並發送訊息 try: #串連服務端 sock.connect((server_ip_1, string.atoi(server_port_1))) while True: #發送頻率 time.sleep(string.atoi(heartbeat_1)) #發送訊息 sock.sendall(dns_codec(msg_1)) #接收並列印訊息 print dns_decode(sock) except socket.error, e: print 'connect server failed. errno = %d, errmsg = %s' % (e.args[0], e.args[1]) sock.close() if __name__ == '__main__': dns_sendmsg()
2、設定檔:
檔案名稱:ens_client_config.ini
內容:
[server_info]ip_1=192.168.1.1port_1=53sockettype_1=UDPheartbeat_1=2msg_1=www.google.com
3、早上測試了下UDP協議下的DNS用戶端,功能正常可用。
a、wireshark抓包:
請求:
響應:
b、代碼運行結果: