利用python構建Mock系統
阿新 • • 發佈:2018-12-30
> 字元 | 位元組順序 | 長度和對齊方式 |
> @ | native | native |
> = | native | standard |
> < | little-endian | standard |
> > | big-endian | standard |
> ! | network (= big-endian) | standard |
例如兩個系統事先定義的通訊格式為:一個整型、兩個長整型、一個長度為8的字元陣列,那麼轉換格式符為:!i2l8s或者!illssssssss
有了上面這個對應表,格式轉換的問題輕鬆搞定,實驗成功可以接收請求和返回內容
3.雖然實現了但還是覺得不夠完美,尤其是response內容的拼裝,是一個個寫死並一個個傳入到pack方法中的,如果response內容很長那麼就顯得特別醜陋而且也不夠靈活。網上找了半天,發現不用一個個傳遞進去,可以先將內容寫入列表或元組中,再在pack方法中用*列表或*元組可實現將這些引數依次傳遞到pack方法中
4.經過上一步驟,程式碼美觀不少,但靈活性依舊沒有解決,於是想到將這些引數變成配置檔案,程式中解析配置檔案內容再將內容寫入列表中再傳遞到方法中,於是網上找了找python怎麼解析xml,方法很多,最終選擇了使用minidom解析,沒有理由,也不知道它的優缺點,只是找到了一個具體的示例並且看懂了於是乎就決定用它了,這個東東的特性以及其他解析方式後續再研究,使用它解析時還是費了一番周折,其實原理就是把xml檔案中的每一個節點當做葉子節點,可以層層解析也可以解析指定的節點,而且節點內容是該節點的子節點(葉子節點)。
<?xml version="1.0" encoding="UTF-8"?> <response> <head> <version>420</version> <command>420</command> <passwd>12345678</passwd> <type>1</type> <status>0</status> <src>4</src> <dest>1</dest> <serializationHigh>1234567</serializationHigh> <serializationLow>7654321</serializationLow> <body_length>60</body_length> <result_length>2</result_length> </head> <result> <iids>2000000001</iids> <gids>10000617005</gids> <similaritys>95</similaritys> <image_type>0</image_type> <dimensions>5</dimensions> </result> <result> <iids>2000000006</iids> <gids>10000617006</gids> <similaritys>95</similaritys> <image_type>0</image_type> <dimensions>5</dimensions> </result> </response>
#!/usr/bin/python # encoding: utf-8 ''' com.test.mockvsearch -- shortdesc com.test.mockvsearch is a description It defines classes_and_methods @author: user_name @copyright: 2013 organization_name. All rights reserved. @license: license @contact: user_email @deffield updated: Updated ''' import sys import struct import string import types from xml.dom import minidom from SocketServer import (TCPServer as SERV,StreamRequestHandler as SRH) # 定義獲取協議頭內容的方法 def gethead(a,b): nodes=a.getElementsByTagName(b).item(0); head=[]; for value in nodes.childNodes: if value.nodeName=='version': head.append(string.atoi(value.firstChild.nodeValue)) elif value.nodeName=='command': head.append(string.atoi(value.firstChild.nodeValue)) elif value.nodeName=='passwd': head.append(str(value.firstChild.nodeValue)) elif value.nodeName=='type': head.append(string.atoi(value.firstChild.nodeValue)) elif value.nodeName=='status': head.append(string.atoi(value.firstChild.nodeValue)) elif value.nodeName=='command': head.append(string.atoi(value.firstChild.nodeValue)) elif value.nodeName=='src': head.append(string.atoi(value.firstChild.nodeValue)) elif value.nodeName=='dest': head.append(string.atoi(value.firstChild.nodeValue)) elif value.nodeName=='serializationHigh': head.append(string.atol(value.firstChild.nodeValue)) elif value.nodeName=='serializationLow': head.append(string.atol(value.firstChild.nodeValue)) elif value.nodeName=='body_length': head.append(string.atoi(value.firstChild.nodeValue)) elif value.nodeName=='result_length': head.append(string.atoi(value.firstChild.nodeValue)) return head; #定義獲取協議體內容的方法 def getbody(element,bodyname): body=[]; nodes=element.getElementsByTagName(bodyname); for i in range(nodes.length): for node in nodes.item(i).childNodes: if node.nodeName=='iids': body.append(string.atol(node.firstChild.nodeValue)); if node.nodeName=='gids': body.append(string.atol(node.firstChild.nodeValue)); if node.nodeName=='similaritys': body.append(string.atoi(node.firstChild.nodeValue)); if node.nodeName=='image_type': body.append(string.atoi(node.firstChild.nodeValue)); if node.nodeName=='dimensions': body.append(string.atoi(node.firstChild.nodeValue)); return body; #定義訊息格式的方法 def getbodyformat(list): format=''; for var in list: if type(var) is types.IntType: format+='i'; if type(var) is types.LongType: format+='Q'; return format; doc = minidom.parse(sys.argv[1]); root= doc.documentElement; #訊息頭格式 headformat="!2i8s4i2q2i" #訊息頭內容 body1=gethead(root,'head'); #訊息體內容 body2=getbody(root, 'result'); #訊息體格式化 bodyformat=getbodyformat(body2); #整個訊息的格式化資訊 rformat=headformat+bodyformat; #整個響應訊息的內容 response=body1+body2; HOST='localhost' PORT=8888; ADDR=(HOST,PORT); #定義請求響應處理類 class MyHandler(SRH): def handle(self): #接收請求 MyData = self.request.recv(2048000); #列印請求長度 print 'result length is:', len(MyData); #列印請求內容和轉換格式 print response,rformat; #拼裝響應內容 senddata=struct.pack(rformat,*response); #傳送響應內容 self.request.send(senddata); #建立Socket服務 myServer=SERV(ADDR,MyHandler); #進入迴圈狀態 myServer.serve_forever();