jmeter BeanShell tcp performance test, detailed examples of sending and receiving data

jmeter sends tcp request instances using beanshell

Based on the near future that may be predicted, there will be a project to test the performance of the tcp protocol interface in the program. In order to avoid being black eyed at that time, under the pressure of leaders, oh no, we should carry out proactive testing activities

tcp sample understanding

  1. Create a new tcp sample

  2. Configure tcp information

  • TCPClient classname: fill in the TCP message format (there are three types). The default prefix is org.apache.jmeter.protocol.tcp.sampler

    TCPClientImpl: normal text transfer
    BinaryTCPClientImpl: hexadecimal message (common)
    LengthPrefixedBinaryTCPClientImpl: inherits the binarytcpcclientimpl class and adds two bytes of data length in front of binarytcpcclientlmpl.

    Tried TCPClientImpl and found that tcp acceptance could not be ended normally, so gave up, so BinaryTCPClientImpl was used

  • End of line(EOL) byte value: the last 2 bits of the response data, which are converted to hexadecimal values. The value range is [- 128127], because the TCP long connection will not be disconnected, we need to judge from the response data and inform the TCP sampler that the request has obtained data / response success

  • SO_ Ringer: this configuration item is used to control whether to wait for the data in the buffer to be sent before closing the connection. If so_ The ringer option specifies
    Value, it will wait for the specified number of seconds to complete the transmission of data in the buffer after receiving the request to close the connection_ When ringer seconds are complete,
    Close the connection. Therefore, if you set this option to 0, all connections will be closed immediately when they receive the closed connection, so as to avoid many problems
    TIME_ Socket with wait status.

  • Other fields can be downloaded by Baidu

beanshell edit

When sending tcp information, because the body length may be different, the last spliced hexadecimal data in the business is inconsistent with what I expected. Therefore, the hexadecimal data can only be spliced by code here.

Specific code

import com.alibaba.fastjson.JSONObject;
public  static String test(){

    	   // Structure of assembly request
        JSONObject object = new JSONObject();
        object.put("uname", "autopf");
        object.put("keytp", "cc");
        object.put("apd", "1.00");
        object.put("seq", "abc_"+"${__threadNum}"+"${counter}");

        // Convert to string
        String dicstr = JSONObject.toJSONString(object);
        System.out.println("Request body to string result: "+dicstr);

        vars.put("tcp_body",dicstr);
		// This Parser class is the code I have referenced and developed, so you guys need to splice it according to different situations of the company
        Parser sss = new Parser();
        //The command field in tcp is different for every interface command
        int cmd = 2;
        // Convert structure to byte format
        byte[] s = dicstr.getBytes();
        System.out.println(s);
        // Call the interface to obtain the spliced tcp header and tcp content
        byte[] msg =  sss.pack(s, cmd);

        System.out.println(new String(msg));
        String tmpmsg = new String(msg);

	   // Convert the spliced tcp data to hexadecimal
	   char[] _16 = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
        StringBuilder sb = new StringBuilder();
        for(int i = 0; i < msg.length;++i){
            sb.append(_16[msg[i]>>4&0xf]).append(_16[msg[i]&0xf]);
        }
	
        System.out.println("sb: " + sb.toString());
	   return sb.toString();
    }

  • ${xxx} is the jmeter variable format, which can be used directly in java code. In this way, the parameterization of request parameters can be solved.
 object.put("seq", "abc_"+"${__threadNum}"+"${counter}");
  • When importing files, pay attention to the path
    Originally, when I wrote this, I would not report an error, but after I wrote the beanshell statement, I would report an error
    source("D:\mytestforJMTER\src\main\java\myjmeter2.java");
    So change to the following mode (local environment: windows):
    source("D:/mytestforJMTER/src/main/java/myjmeter2.java");

  • The Parser class in the code is the code I referenced and developed, so you guys need to splice the last hexadecimal data according to different situations of the company

  • Import the corresponding jar package
    I directly put the jar package in the jmeter directory
    Then restart jmeter and no error will be reported

    When the beanshell is ready, it's time to send

Send request

Reference jmeter variable defined in beanshell

Assert

Add a response assertion and manually convert the content to be asserted into hexadecimal.
In this way, we have completed a simple tcp request and response judgment

Hey, you'll have doubts again at this time. Do I assert that I have to look at hexadecimal every time and splice it myself? It's not tiring

Well, under the heavy pressure of the external environment, I embarked on the hard road of finding the truth again

Get the tcp response result, convert the bean shell into a string, and then assert

  • To be honest, I don't think there is a suitable sampler to obtain tcp results. Only regular samplers can be used
    -Just write a regular. The doubt is that. * this rule can be implemented, but. * + this rule cannot be implemented. I've been wondering for a long time
    In this way, I naively think I can get the results. The result is null....

    There's no way. I've run out of skills here. Then I can only go to Du Niang's arms to find comfort. I found that many bosses said it was best to open a debug sampler.
    OK, arrange it
    In fact, I don't know the difference between debug sample and debug postprocessor, but it doesn't affect us to try.

  • You can see the results in the figure below. It is speculated that this should also be the built-in variable of jmeter. Although the regular function does not get a value, we can determine the return value we need according to this modulator.
    tcp_result=null
    tcp_result_g=0
    tcp_result_g0=2b02xxxxx

  • I would be grateful if someone could tell me why

    Well, in the previous step, we have obtained the response result of the tcp request, and the next step is to convert hexadecimal

beanshell processes the returned results

As before, add a beanshell sampler, write java code, and then return the final result to the custom jmeter variable

Of course, the parser here is also developed for me.

Finally, here you can use assertions to operate normally, and you don't need to do hexadecimal

be careful

  1. Add debug sampler
  2. You need to add the java file to use or import the jar package of the response
  3. For the code written by beanshell, if an error is reported but the information is not obvious, you can also add try catch
	try {
	    JsonClientUtil jcu=new JsonClientUtil();
	    ObjectNode node = JsonUtil.createObjectNode();
	}catch (Throwable ex) {
	    log.error("Beanshell failure: ", ex);
	    throw ex;
	}

Splicing and converting hexadecimal codes

  • myjmeter2.java, code can refer to
class data_viewer {

	public static void write_short_le(byte[] buf, int offset, short value) {
		buf[offset + 1] = (byte) ((value >> 8) & 0xff);//Description I
		buf[offset + 0] = (byte) ((value) & 0xff);
	}

	public static void write_int_le(byte[] buf, int offset, int value) {
		buf[offset + 3] = (byte) ((value >> 24) & 0xff);//Description I
		buf[offset + 2] = (byte) ((value >> 16) & 0xff);
		buf[offset + 1] = (byte) ((value >> 8) & 0xff);
		buf[offset + 0] = (byte) (value & 0xff);
	}

	public static void write_bytes(byte[] src, int src_offset, byte[] dst, int dst_offset) {
		for(int i = 0 ; i < src.length - src_offset; ++i) {
			dst[dst_offset +i] = src[src_offset + i];
		}
		//System.out.println("bytes.length: " + (src.length - src_offset));
		//System.arraycopy(src, src_offset, dst, dst_offset, src.length - src_offset);
	}

	public static short read_short_le(byte[] data, int offset) {
		int ret = (data[offset] | (data[offset + 1] << 8));
		return (short) ret;
	}

	public static int read_int_le(byte[] data, int offset) {
		int ret = ((data[offset]&0xFF) | ((data[offset + 1]&0xFF) << 8) | ((data[offset + 2]&0xFF << 16)) | ((data[offset + 3]&0xFF << 24)));
		return ret;
	}

}


class Parser {

	static final int HEAD_SIZE = 10;
	static final int TOTAL_SIZE = 14;
	int my_cmd;
	String my_json;

	public String parse(byte[] bytes) {
		int offset = 0;
		int plen = data_viewer.read_int_le(bytes, offset);
		offset += 4;//pkgLen
		offset += 4;//checkSum
		my_cmd = data_viewer.read_short_le(bytes, offset);
		offset += 2;//cmd
		offset += 2;//target
		offset += 2;//retCode
		int content_size = (plen - HEAD_SIZE);
		byte[] content_buf = new byte[content_size];
		data_viewer.write_bytes(bytes, offset, content_buf, 0);
		my_json = new String(content_buf);
		return my_json;
	}

	public static byte[] pack(byte[] content,int cmd) {
		int total_size = content.length + TOTAL_SIZE;
		int pkgLen = total_size - 4;
		int offset = 0;
		byte[] msg = new byte[total_size];
		data_viewer.write_int_le(msg, offset, pkgLen);
		offset += 4;//pkgLen
		data_viewer.write_int_le(msg, offset, 0);
		offset += 4;//checkSum
		data_viewer.write_short_le(msg, offset, (short)cmd);
		offset += 2;//cmd
		data_viewer.write_short_le(msg, offset, (short) 0);
		offset += 2;//target
		data_viewer.write_short_le(msg, offset, (short) 0);
		offset += 2;//retCode
		data_viewer.write_bytes(content, 0, msg, offset);
		return msg;
	}
}


Reference documents

  1. https://blog.51cto.com/u_6183574/2511391
  2. https://www.cnblogs.com/xiyozhang136/p/7687760.html
  3. https://blog.csdn.net/slsunxia/article/details/107710547
  4. https://www.thinbug.com/q/39677810
  5. https://www.cnblogs.com/bf-blackfish/p/10579867.html
  6. https://www.cnblogs.com/hetutu-5238/p/10648116.html

Tags: jmeter

Posted on Thu, 16 Sep 2021 17:45:37 -0400 by dhodge