1. 程式人生 > >利用python構建Mock系統

利用python構建Mock系統

> 字元 位元組順序 長度和對齊方式
> @ 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();