浅谈配置元件之TCP取样器配置/TCP取样器

浅谈配置元件之TCP取样器配置/TCP取样器

1.引言

在进行网络性能测试时,TCP取样器配置和TCP 取样器(TCP Sampler)是两个重要的组件,他们允许用户直接发送和接收TCP 数据包,这对于测试服务器的TCP 连接处理能力、模拟特定的TCP 交互场景非常有用。本文档将详细介绍如何在JMeter中配置和使用TCP 取样器配置和TCP取样器使用,因为两者基本一样,所以两个放在一起讲解。

2.添加TCP 取样器配置/TCP 取样器

添加TCP取样器配置

  1. 新建线程组:首先,在测试计划中右击,选择“添加” > “Threads(Users)” > “线程组(Thread Group)”,添加一个线程组
  2. 添加TCP 取样器配置:在刚刚创建的线程组内,右击选择“添加” > “配置元件” > “TCP 取样器配置(TCP Sampler Config)”。
    添加TCP取样器
  3. 新建线程组:首先,在测试计划中右击,选择“添加” > “Threads(Users)” > “线程组(Thread Group)”,添加一个线程组
  4. 添加TCP 取样器:在刚刚创建的线程组内,右击选择“添加” > “取样器(Sampler)” > “TCP 取样器(TCP Sampler)”。

3.配置TCP 取样器

TCP 取样器的配置界面提供了多个参数,以满足不同的测试需求:
● TCPCllient classname:
TCP Sampler提供了3个报文编码类型的实现,分别是
1.org.apache.jmeter.protocol.tcp.sampler. TCPClientImp
2.org.apache.jmeter.protocol.tcp.sampler. BinaryTCPClientImpl
3.org.apache.jmeter.protocol.tcp.sampler. LengthPrefixedBinaryTCPClientImpl
1)TCPClientImpl以文本编辑器中所编辑的纯文本为内容进行发送。
2)BinaryTCPClientImpl以文本编辑器中所编辑的16进制字符(hex)内容为基础转换为二进制的
字节内容进行发送。
3)LengthPrefixedBinaryTCPClientImpl在BinaryTCPClientImpl基础上默认以发送内容的长度为
字节前缀进行填充。
案例说明的时候会根据不同的情况进行举例说明。
● 服务器名称或IP:输入目标服务器的域名或IP地址。
● 端口号:指定服务器上监听的TCP端口。
● 超时连接:与服务器套接字应用连接超时时间(毫秒)
● 超时时间:响应超时时间(毫秒),这个值的设置跟End of line(EOL) byte value有关系,如果End of line(EOL) byte value中的值设置不正确,会导致JMeter一直在等待无法结束,但是如果指定了Response Timeout这个值的话,在到达这个值的时候就关闭连接
● 重用连接(Re-use connection):勾选后,将在同一个线程内重用TCP连接,对于需要多次交互的测试场景非常有用。
● 关闭连接:测试结束后是否关闭连接。
● 设置无延迟:是否需要使用该选项,需要跟实际的业务情况结合
● SO_LINGER:该配置项用于控制在关闭连接之前是否要等待缓冲区中的数据发送完成。如果SO_LINGER选项指定了值,则在得到关闭连接的请求之后还会等待指定的秒数以完成缓冲区中数据的发送,在指定的SO_LINGER秒数完成后,关闭连接。因此,如果你把该选项设置成0,那么所有连接在收到关闭连接的时候都会立即关闭,避免产生很多处于TIME_WAIT状态的套接字。
● End of line(EOL) byte value:响应数据的最后2位,转换为10进制的值。取值区间[-128,127]。
● 要发送的文本:在此处输入要发送到服务器的数据。根据协议和需求,这可以是任何文本或二进制数据。

4.案例说明

情况1:TCPClientImp模式

  1. 后端测试代码如下
package com.test;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class tcp {
    public static void main(String[] args) throws Exception {
        // 监听的端口号
        int portNumber = 9002;
        // 创建 ServerSocket 对象
        ServerSocket serverSocket = new ServerSocket(portNumber);
        System.out.println("等待客户端连接...");

        while (true) {
            // 接受客户端的连接请求
            Socket client = serverSocket.accept();
            System.out.println("客户端已连接,IP地址:" + client.getInetAddress().getHostAddress());
            // 创建用于读取客户端发送的数据的输入流
            BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
            System.out.println(in.readLine());
            // 创建用于向客户端发送数据的输出流
            PrintWriter out = new PrintWriter(client.getOutputStream(), true);
            out.println("hello Client");
            out.flush(); // 刷新缓冲区,保证数据已被发送
            // 关闭连接
            in.close();
            out.close();
            client.close();

        }
    }
}

TCPCllient classname选择TCPClientImp,jmeter.properties中设置为tcp.handler=TCPClientImpl,服务器名称或IP设置127.0.0.1,端口号设置9002,要发送的文本设置为{“a”: “b”,“c”: “d”},其他默认
运行脚本,查看结果树,在响应数据的Response Body中可以看到信息:hello Client

情况2:BinaryTCPClientImpl模式

  1. 后端测试代码如下
package com.test;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class tcp {
    public static void main(String[] args) throws Exception {
        // 监听的端口号
        int portNumber = 9002;
        // 创建 ServerSocket 对象
        ServerSocket serverSocket = new ServerSocket(portNumber);
        System.out.println("等待客户端连接...");
        while (true) {
            // 接受客户端的连接请求
            Socket client = serverSocket.accept();
            System.out.println("客户端已连接,IP地址:" + client.getInetAddress().getHostAddress());
            // 创建用于读取客户端发送的数据的输入流
            InputStream inputStream = client.getInputStream();
            // 读取数据
            byte[] buffer = new byte[1024];
            int bytesRead;
            StringBuilder data = new StringBuilder();
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                // 将读取到的数据转换为字符串并添加到data中
                data.append(new String(buffer, 0, bytesRead));
                break;
            }
            System.out.println("接收到的数据:\n" + data.toString());
            PrintWriter out = new PrintWriter(client.getOutputStream(), true);
            out.println("OK");
            out.flush(); // 刷新缓冲区,保证数据已被发送
            // 关闭连接
            out.close();
            client.close();

        }
    }
}

TCPCllient classname选择BinaryTCPClientImpl,jmeter.properties中设置为tcp.handler=BinaryTCPClientImpl,服务器名称或IP设置127.0.0.1,端口号设置9002,要发送的文本设置为697427732074696d6520746f20706c61792e,使用在线工具(https://www.sojson.com/hexconvert/16to10.html)可以获取范围该内容为:it’s time to play.行尾(EOL)字节值使用10,其他默认运行脚本,查看结果树,在响应数据的Response Body中可以看到信息:4f4b0d0a,该数据进行翻译以后即为测试代码中OK的字符。

情况3:LengthPrefixedBinaryTCPClientImpl模式

根据情况2,发现发送内容无区别,但是在响应数据中可以看到不一样。

情况4:Re-use connection模式

后端测试代码如下

package com.test;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

public class tcp {
    public static void main(String[] args) throws Exception {
        // 监听的端口号
        int portNumber = 9002;
        // 创建 ServerSocket 对象
        ServerSocket serverSocket = new ServerSocket(portNumber);
        System.out.println("等待客户端连接...");

        while (true) {
            // 接受客户端的连接请求
            Socket client = serverSocket.accept();
            System.out.println("客户端已连接,IP地址:" + client.getInetAddress().getHostAddress());
            int remotePort = client.getPort();
            // 创建用于读取客户端发送的数据的输入流
            System.out.println("remotePort:" + remotePort);
            InputStream inputStream = client.getInputStream();
            // 读取数据
            byte[] buffer = new byte[1024];
            int bytesRead;
            StringBuilder data = new StringBuilder();
            while ((bytesRead = inputStream.read(buffer)) != -1) {
                // 将读取到的数据转换为字符串并添加到data中
                data.append(new String(buffer, 0, bytesRead));
                break;
            }
            System.out.println("接收到的数据:\n" + data.toString());
            PrintWriter out = new PrintWriter(client.getOutputStream(), true);
            out.println("OK");
            out.flush(); // 刷新缓冲区,保证数据已被发送
            // 关闭连接
            out.close();
            client.close();

        }
    }
}

主要就是将关闭连接的代码取消,并且将线程组中的循环次数设置为2

未勾选Re-use connection,未勾选关闭连接
  1. 当我们未勾选的时候,进行TCP测试,可以看到java后台打印的信息如下
等待客户端连接...
客户端已连接,IP地址:10.33.123.18
remotePort:1066
接收到的数据:
it's time to play.
客户端已连接,IP地址:10.33.123.18
remotePort:1067
接收到的数据:
it's time to play.
勾选Re-use connection,未勾选关闭连接
  1. 当我们未勾选的时候,进行TCP测试,可以看到java后台打印的信息如下
客户端已连接,IP地址:10.33.123.18
remotePort:27770
接收到的数据:
it's time to play.
勾选Re-use connection,勾选关闭连接
  1. 当我们勾选的时候,在未测试TCP时,我们首先看下当前在只启动后台的情况下,TCP的监听情况
客户端已连接,IP地址:10.33.123.18
remotePort:13723
接收到的数据:
it's time to play.
客户端已连接,IP地址:10.33.123.18
remotePort:13724
接收到的数据:
it's time to play.
情况5:超时(毫秒):连接

超时(毫秒)中将连接设置为1,即1毫秒内需要建立连接,否则超时,其他参数不变,进行TCP测试,可以在查看结果树中看到如下结果:

Error Count: 1
Data type ("text"|"bin"|""): 
Response code: 500
Response message: java.net.SocketTimeoutException
情况6:超时(毫秒):响应

超时(毫秒)中将响应设置为1,即1毫秒内需要建立连接,否则超时,其他参数不变,进行TCP测试,可以在查看JMeter日志中看到如下结果:

Caused by: java.net.SocketTimeoutException: Read timed out
    at java.net.SocketInputStream.socketRead0(Native Method) ~[?:1.8.0_101]
    at java.net.SocketInputStream.socketRead(SocketInputStream.java:116) ~[?:1.8.0_101]
    at java.net.SocketInputStream.read(SocketInputStream.java:170) ~[?:1.8.0_101]
    at java.net.SocketInputStream.read(SocketInputStream.java:141) ~[?:1.8.0_101]
    at java.net.SocketInputStream.read(SocketInputStream.java:127) ~[?:1.8.0_101]
    at org.apache.jmeter.protocol.tcp.sampler.BinaryTCPClientImpl.read(BinaryTCPClientImpl.java:134) ~[ApacheJMeter_tcp.jar:5.1.1 r1855137]
    ... 6 more

5.总结

通过上述步骤,你可以有效地配置和利用JMeter的TCP 取样器来进行TCP层面的性能和功能测试。无论是简单的连接测试,还是复杂的交互协议模拟,TCP 取样器都提供了强大的支持。记得在实际测试前,充分理解你的测试目标,并根据需要调整取样器的配置选项,以确保测试的有效性和准确性。

### TCP取样器无法接收数据的原因分析 当遇到TCP取样器无法接收数据的情况时,可能涉及多个方面的问题。以下是可能导致此现象的一些常见原因及其解决方案: #### 配置错误 如果TCP取样器配置不正确,则可能会导致其无法正常工作。例如,端口号、IP地址或其他网络参数设置不当都可能是问题所在[^1]。 #### 数据传输中的异常情况 有时,在数据传输过程中可能出现一些意外状况,比如由于支持ES3.1失败而导致的日志记录不足,这会使得调试变得困难。改进日志功能可以帮助定位此类问题的发生位置和根本原因。 #### 软件缺陷修复的影响 之前存在一个问题,即某些头文件包含了不应该存在于发布版本中的大量测试数据(约64KB),这一问题已被修正,现在这些不必要的部分已经被适当地移除[^2]。尽管如此,仍需确认该改动是否影响到当前使用的环境以及是否存在其他未被发现的相关漏洞。 ### 解决方案建议 为了有效处理上述提到的各种可能性并找到具体解决办法,请尝试按照下面的方法逐一排查: 1. **检查配置**: 确认所有关于目标服务器的信息均准确无误地填入到了相应的字段当中;特别是要注意验证所指定的目标主机名或者IP地址还有对应的监听端口是否匹配实际运行的服务实例。 2. **启用增强型日志机制**: 如果怀疑是因为缺乏足够的诊断信息而难以判断故障源头的话,可以考虑开启更详细的追踪模式来收集更多上下文线索以便进一步分析。通过引入更加完善的日志管理策略能够极大地促进对此类事件的理解程度。 3. **更新至最新稳定版软件包**: 给定先前已知的一个潜在隐患已经得到了妥善处置的事实表明保持应用程序始终处于最新的维护状态对于预防未知风险至关重要。因此强烈推荐升级到包含所有必要补丁程序的新发行版本之上执行重新评估操作。 ```python import socket def tcp_sampler(host='localhost', port=9090, timeout=5): try: with socket.create_connection((host, port), timeout) as sock: message = b'Hello, world' sock.sendall(message) data = sock.recv(1024) return f"Received {data!r}" except Exception as e: return str(e) if __name__ == "__main__": result = tcp_sampler() print(result) ``` 以上脚本提供了一个简单的Python实现用于模拟发送消息给远程服务并通过读取消息响应来进行基本的功能检测过程演示如何建立连接及交换少量字节流内容作为初步验证手段之一。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奔波儿灞爱霸波尔奔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值