代理工具的核心框架如上,分为代理服务、操作界面、主函数。代理服务模块用于创建一个代理对象,进行C<–>agentServer<–>S的通信主流程,在agentServer中进行四块业务:创建两个连接,用于连接C端和S端,方便用于消息的转发;接入协议解析模块,进行协议的快速解析;对接操作界面window,将解析数据发送至展板,同时接收来自展板的数据;对接测试用例配置数据,读取数据并进行协议定制化发送。
class AgentServer():
def __init__(self,server_address,agent_port):
self.agentServer=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
self.agentServer.bind(("127.0.0.1",agent_port))
self.agentServer.listen(5)
self.server_address=server_address
self.agent_obj=None
def start(self,ui):
#代理服务器等待客户端连接
client_sock,addr=self.agentServer.accept()
if client_sock:
#客户端连接成功后 创建一个代理客户端连接服务器
server_sock=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
server_sock.connect(self.server_address)
self.agent_obj=Agent(client_sock,server_sock,ui)
self.agent_obj.start()
def stop(self):
self.agent_obj.stop()
self.agent_obj=None
self.agentServer.close()
def send(self,cmd,dataL):
self.agent_obj.agent_reSend_to_server(cmd,dataL)
class Agent():
def __init__(self,client_sock,server_sock,ui):
self.ui=ui
self.recv =b""
self.send =b""
self.client_sock=client_sock
self.server_sock=server_sock
self.alive=True
#指定协议号,用于筛选协议 注意由于协议字段格式问题 有且仅支持3位协议号头 和5位协议号筛选,分别用于协议大类筛选和指定协议筛选
self.protocol=int(ui.protocol) or 0
self.send_readFmt=protocolTransTool.ReadFmt()
self.recv_readFmt=protocolTransTool.ReadFmt()
self.pack_tool=protocolTransTool.ProtocolTool()
def agent_send_to_client(self):
while self.alive:
try:
#这里的data是byte类型
data=self.server_sock.recv(1024)
if data:
# print("send_to_client:",data)
#服务器返回给代理的数据 转发给客户端
self.client_sock.send(data)
self.recv=self.recv+data
except Exception as e:
self.alive=False
print(e)
def agent_send_to_server(self):
while self.alive:
try:
data=self.client_sock.recv(1024)
if data:
# print("send_to_server:", data)
#将客户端的协议数据 通过代理连接发送给 服务器端
self.server_sock.send(data)
self.send=self.send+data
except Exception as e:
self.alive=False
print(e)
定义代理的启动和关闭方法,采用多线程方式,分别用于协议转发和协议解析,同时代理关联UI,需要跟UI一同关闭,这里定义线程为守护线程
def start(self):
send_to_client_td=threading.Thread(target=self.agent_send_to_client,args=())
send_to_server_td=threading.Thread(target=self.agent_send_to_server,args=())
transClient_td=threading.Thread(target=self.transClient,args=())
transServer_td=threading.Thread(target=self.transServer,args=())
#设置守护线程 跟随主线程关闭
send_to_server_td.daemon=True
send_to_client_td.daemon=True
transServer_td.daemon=True
transClient_td.daemon=True
send_to_client_td.start()
send_to_server_td.start()
transClient_td.start()
transServer_td.start()
def stop(self):
self.alive=False
其他关联方法:协议解析方法、代理二次封包方法。这里由于涉及到具体的定制解析内容,就不上代码了,简单说下思路:解析方法调用解析方法获得协议号,然后根据协议与设置的协议号self.protocol 进行对比,用作协议筛选,然后利用反射的方式调用对应协议的解析方法,实现数据的解析,然后将数据打包成数组发送至window展板。二次封包方法则是直接拿到window输入的数据,按定制的包体进行封包,然后转发的C端。PS:这里要注意解析方法返回的数组格式最好跟window输入的格式保持一致,方便解析,我这边采用是数组嵌套数组的方式,大概是[protocol,[data]]的形式