mina socket登录性能测试
本帖最后由 重爱 于 2016-5-25 12:41 编辑mina socket 做的登录,客户端的原理,先生成json串(这个是我们拼接的发送报文,其中的用户名等要做参数化),再进行加密(加密规则问开发),再进行gzip加压,生成iobuffer,向服务端发送。
服务端原理,有个IP,一个端口,监听来自客户端的请求,接收iobuffer,进行gunzip解压,解密。转成json串。响应后再按加密和gzip发给客户端
客户端接收到服务端的响应信息,再进行gunzip解压,解密后转后json串(这个是我们判断响应是否正确的地方)
1.使用抓包工具,发现iobuffer的字节流没办法找出做参数化规律
2.便想从json串的地方开始做参数化,然后去查看工程,断点发登录的过程,得到json串。再找出加密和加压规则,生成iobuffer
3.eclipse写成的脚本
<blockquote>package com.test;
4.转成jmeter脚本
package jmeter;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import net.sf.json.JSONObject;
import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.protocol.java.sampler.AbstractJavaSamplerClient;
import org.apache.jmeter.protocol.java.sampler.JavaSamplerContext;
import org.apache.jmeter.samplers.SampleResult;
/**
*socket 测试jmeter脚本
* @author wenhuang
*
*/
public class LoginSocketTestJmeter extends AbstractJavaSamplerClient {
private String Ip;
private int Post;
private String user;
private String password;
private String resultData;
// 这个方法是用来自定义java方法入参的。
//设置可用参数及的默认值;
public Arguments getDefaultParameters() {
Arguments params = new Arguments();
params.addArgument("Ip", "192.168.1.1");
params.addArgument("Post", "1111");
params.addArgument("user", "test");
params.addArgument("password", "1111");
return params;
}
//每个线程测试前执行一次,做一些初始化工作;
public void setupTest(JavaSamplerContext arg0) {
}
//开始测试,从arg0参数可以获得参数值;
public SampleResult runTest(JavaSamplerContext arg0) {
Ip = arg0.getParameter("Ip");
Post = arg0.getIntParameter("Post");
user = arg0.getParameter("user");
password = arg0.getParameter("password");
String json = "{\"test\":0,\"data\":{\"user\":\""+user+"\",\"password\":\""+password+"\"},\"key\":\"0\"}";
SampleResult sr = new SampleResult();
sr.setSampleLabel("登录");//设置样品标签
sr.setResponseMessage("请求的JSON: "+ json);
try {
sr.sampleStart();// jmeter 开始统计响应时间标记
//1.创建客户端Socket,指定服务器地址和端口
Socket socket=new Socket(Ip, Post);
//2.获取输出流,向服务器端发送信息
OutputStream os=socket.getOutputStream();//字节输出流
os.write(getSendHex(json));
os.flush();
//3.获取输入流,并读取服务器端的响应信息
InputStream is=socket.getInputStream();
resultData = getReceiveJson(is);
//4.关闭资源
if(os != null){
os.close();
}
if(is != null){
is.close();
}
if(socket != null){
socket.close();
}
System.out.println("接收到的json ="+resultData);
JSONObject jsonObj = JSONObject.fromObject(resultData);
String codeNum = jsonObj.get("code").toString();
if (Integer.parseInt(codeNum) == 200){
sr.setSuccessful(true);
System.out.println("登录成功,返回code ="+codeNum);
//sr.setResponseMessage("请求的JSON: "+ json + " 登录成功,返回code ="+codeNum); //输出在查看结果树-的取样器结果中
}else{
sr.setSuccessful(false);
System.out.println("登录失败,返回code ="+codeNum);
//sr.setResponseMessage("请求的JSON: "+ json + " 登录失败,返回code ="+codeNum);
}
// 通过下面的操作就可以将被测方法的响应输出到Jmeter的察看结果树中的响应数据里面了。
if (resultData != null && resultData.length() > 0) {
sr.setResponseData("返回结果是:"+resultData, null);//输出在查看结果树-的响应结果中
sr.setDataType(SampleResult.TEXT);
}
// System.out.println(resultData);
} catch (Throwable e) {
sr.setSuccessful(false);
e.printStackTrace();
} finally {
sr.sampleEnd();// jmeter 结束统计响应时间标记
}
return sr;
}
//测试结束时调用;
public void teardownTest(JavaSamplerContext arg0) {
//System.out.println(end);
//System.out.println("The cost is"+(end-start)/1000);
}
// main只是为了调试用,最后打jar包的时候注释掉。
/*
public static void main(String[] args)
{ // TODO Auto-generated method stub
for (int i =0;i<5;i++){
Arguments params = new Arguments();
params.addArgument("Ip", "192.168.1.111");//设置参数,并赋予默认值
params.addArgument("Post", "1111");//设置参数,并赋予默认值
params.addArgument("user", "test");//设置参数,并赋予默认值
params.addArgument("password", "1111");
JavaSamplerContext arg0 = new JavaSamplerContext(params);
LoginSocketTestJmeter test = new LoginSocketTestJmeter();
test.setupTest(arg0);
test.runTest(arg0);
test.teardownTest(arg0);
}
}
*/
}
5.将相关类打包成jar包放在 X:\apache-jmeter-3.0\lib\ext目录下,使用jmeter进行压测试
:L package com.test;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
import net.sf.json.JSONObject;
import org.apache.mina.core.buffer.IoBuffer;
//这两个加密加压的包根据项目修改
import com.tools.Des3;
import com.tools.ZLibUtils;
/**socket 发送消息,和接收消息 测试脚本
* @author Administrator
*
*/
public class LoginSocketTest {
public static void main(String[] args) throws Exception {
try {
//1.创建客户端Socket,指定服务器地址和端口
Socket socket=new Socket("192.168.1.1", 11111);
//2.获取输出流,向服务器端发送信息
OutputStream os=socket.getOutputStream();//字节输出流
//PrintWriter pw=new PrintWriter(os);//将输出流包装为打印流
String json = "{\"test\":0,\"data\":{\"user\":\"test\",\"password\":\"test\"},\"key\":\"0\"}";
//将json转成16进制的字节流
os.write(getSendHex(json));
//发送
os.flush();
//socket.shutdownOutput();//关闭输出流
//3.获取输入流,并读取服务器端的响应信息
InputStream is=socket.getInputStream();
//将接收的字节流转成json
String recjson = getReceiveJson(is);
//判断结果是否正确将json转为object对象,取出要判断的参数值code做断言。
JSONObject jsonObj = JSONObject.fromObject(recjson);
String codeNum = jsonObj.get("code").toString();
System.out.println("code="+codeNum);
//4.关闭资源
if(os != null){
os.close();
}
if(is != null){
is.close();
}
if(socket != null){
socket.close();
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* json转为客户端发送的16进制报文
* @param json
* @return
* @throws Exception
*/
public static byte[] getSendHex(String json) throws Exception {
System.out.println("json ="+json);
IoBuffer buff = IoBuffer.allocate(1024).setAutoExpand(true);
//加密规则,根据项目做修改
json = Des3.encode(json, "test");
//加压
byte[] bytes = ZLibUtils.compress(json.getBytes("UTF-8"));
//装bytes存入buff
buff.putInt(bytes.length);
buff.put(bytes);
buff.flip();
// 将buff转为 字节 再转为16进制
byte[] b = new byte;
buff.get(b);
return b;
}
/**
* byte数组转换成16进制字符串
*
* @param src
* @return
*/
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder();
if (src == null || src.length <= 0) {
return null;
}
for (int i = 0; i < src.length; i++) {
int v = src & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
stringBuilder.append("\\x");
}
//16进制前面要加\x
return ("\\x"+stringBuilder.substring(0,stringBuilder.length()-2)).toString();
}
/**
* 字节流转int型
* @param b
* @return
*/
public static int b2i(byte[] b) {
int value = 0;
for (int i = 0; i < 4; i++) {
int shift = (4 - 1 - i) * 8;
value += (b & 0x000000FF) << shift;
}
return value;
}
/**客户端得接收服务端返回的iobuffer并转成json
* 接收的iobuffer,前四个字节是表示字节流的长度,先接收前四个字节,并用16进制转10进制int型方法,得到长度的数字
* 再根据长度接收所有的字节流。如果长度错误,拨收是会出错的。
* @param is socket的输入流
* @return json
* @throws Exception
*/
public static String getReceiveJson(InputStream is) throws Exception{
byte[] intByte = new byte;
is.read(intByte);
int msgLength = b2i(intByte);
System.out.println("int:"+msgLength);
int readPosition = 0;
byte[] byteArray = new byte;
while(readPosition < msgLength){
int value = is.read(byteArray, readPosition, msgLength-readPosition);
if(value == -1){
break;
}
readPosition += value;
}
byte[] data = ZLibUtils.decompress(byteArray); //解压
String code = new String(data, "UTF-8");
String text = Des3.decode(code, "test"); //解密
System.out.println("服务端接收消息内容为:="+text);
return text;
}
}
上一步是做什么的?
支持下~
页:
[1]