Python 建立TCP连接通信 并接收Jmeter发送的XML报文

Python 建立TCP连接,并接收Jmeter发送过来的xml报文


前言

TCP连接对于一个客户端程序来说,建立一个socket需要两个步骤。

首先,您需要建立一个实际的socket对象。其次,您需要把它连接到远程服务器上。

在建立socket对象的时候,您需要告诉系统两件事:通信类型和协议家族。通信类型指明用什么协议来传输数据。协议的例子包括IPv4(当前的Internet标准),IPv6(将来的Internet标准),IPX/SPX(NetWare)和AFP(Apple文件共享)。到目前为止最通用的是IPv4。

协议家族则定义数据如何被传输,通信类型基本上都是:AF_INET(和IPv4对应)。协议家族表示TCP通信的SOCK_STREAM和表示UDP通信的SOCK_DGRAM


一、Socket

套接字模块是一个非常简单的基于对象的接口,它提供对低层BSD套接字样式网络的访问。使用该模块可以实现客户机和服务器套接字。要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。利用该模块包含的函数和类定义,可生成通过网络通信的程序

二、使用步骤

1.安装并引入库

pip install socket

import socket

2.封装建立socket连接的方法

def socket_connet(ip,port):
	sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 实例化一个基于tcp的socket对象
	sk.bind((ip, port)) # 使用ip port建立连接
	sk.listen(5)   # 设置监听
	return sk

3.封装接收xml报文的方法

def get_xml_message(client,log):

    # 先接收20字符
    recv_front_20 = client.recv(20)
    while len(recv_front_20) < 20:
        recv_front_20 = recv_front_20 + client.recv(20)
    log.info("前20字符: " + str(recv_front_20))

    # 正则匹配出报文长度
    recv_front_20_num = re.match(r'^(.*)<', recv_front_20.decode('utf-8'))
    message_len = recv_front_20_num.group(1)
    message_len = re.findall('\d+', message_len)[0]
    message_len = message_len[-6:]
    log.debug("报文长度: " + str(message_len))

    # 报文中除了长度还可能有项目标识 例如:CBS 001034
    string_len = re.match(r'(.+(?=<))', recv_front_20.decode('utf-8'))
    log.debug('string_len: ' + str(string_len))
    frame_len = string_len.group(1)
    log.debug("实际报文长度: " + frame_len)

    total_data = recv_front_20
    total_len = 20

    if (message_len.isdigit()):
        # 最终的报文长度=报文实际长度+长度所占字节的长度
        iFrameLen = int(message_len) + len(frame_len)
        log.info("报文总长度: " + str(message_len) + " + " + str(len(frame_len)) + " = " + str(iFrameLen))

        while total_len < iFrameLen:
            # 读报文
            frameData = client.recv(1024)
            log.debug("-----先读取1024字节: " + str(frameData))
            # 拼接
            total_data = total_data + frameData
            log.debug("-----前20内容+获取1024内容:" + str(total_data))
            # 获取长度
            total_len = len(total_data)
            log.debug("-----获取后的总长度:" + str(total_len))

    else:
        log.error("正则抓取到的报文长度不是纯数字,请排查!")

    frame_data = total_data[len(frame_len):]

    # 设置编码格式
    frame_data = frame_data.decode('utf-8', 'ignore')

    # 判断报文是否为空
    if frame_data == '':
        log.error('报文不能为空 !')
        exit()
    log.info("收取到的报文:\n {}".format(frame_data))

    # xml转bytes 方便etree处理
    xml = bytes(bytearray(frame_data, encoding='utf-8'))

    # 格式化转换xml报文 为以后xpath提供方便
    xml_data = etree.XML(xml)
    log.debug('xml_data: ' + str(xml_data))

    return xml_data

4 启动程序

if __name__ == '__main__':
	# 初始化日志
    log = get_log('test.log','info')
    ip='127.0.0.1'
    port=9996
    sk = socket_connet(ip,port)
    # 持续接收
    while True:
    	client = sk.accept()
    	if client: # 监听到有接收,则调用接收xml的方法
    		xml_data = get_xml_message(client,log) # get_log 是封装的日志方法
    		

封装通用的日志模块

def get_log( filename, level,when='MIDNIGHT', backupCount=3, maxBytes=10000000, fmt='%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'):

    level = __level_dict.get(level.lower(), None)
    logger = logging.getLogger(filename)  # 设置日志名称
    format_str = logging.Formatter(fmt)  # 设置日志格式
    logger.setLevel(level)  # 设置日志级别
    console_handler = logging.StreamHandler()  # 控制台输出
    console_handler.setFormatter(format_str)  # 控制台输出的格式
    logger.addHandler(console_handler)  # 控制台输出
    file_handler = handlers.RotatingFileHandler(filename=filename, maxBytes=maxBytes, backupCount=backupCount, encoding='utf-8')  # 文件输出
    file_handler.setFormatter(format_str) # 文件输出格式
    logger.addHandler(file_handler) # 日志输出
    return logger

5 Jmeter 发送TCP请求

使用Jmeter向启动的服务端发送消息

6 服务端收到发来的消息

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值