背景:websocket在Html5里面有着举足轻重的地位,最近工作中需要对websocket接口进行压测,使用jmeter的websocket
sample进行,但是一般现网的websocket都是采用的wss://协议,直接使用ws://协议的较少,毕竟安全还是非常重要的,这里就涉及到ssl协议,模拟websocket客户端,使用证书和公钥,摸索了半天终于摸索出来了。
java websocket client
java 中模拟websocket client请参考 https://github.com/TooTallNate/Java-WebSocket, 里面有非常详细的说明。
maven项目中引入
<dependency>
<groupId>org.java-websocket</groupId>
<artifactId>Java-WebSocket</artifactId>
<version>1.4.0</version>
</dependency>
然后参考 https://github.com/TooTallNate/Java-WebSocket/wiki#client-example, 里面有很详细的说明,就不在累述,我这边主要针对wss的情况进行代码说明
什么是wss
wss 是 Web Socket Secure 的简称, wss是websocket 在TLS之上的加密版本。
如何获取证书,并使用keytool工具生成本地store秘钥文件
证书可以从chrome浏览器上获取,如何获取请参考 https://jingyan.baidu.com/article/90895e0f34fad464ec6b0b1e.html
使用如下命令在目录下面生成my.store文件
keytool -import -alias "my.store" -file wss.cer -keystore my.store
websocket ssl client 代码示例
首先继承抽象类WebSocketClient,并实现websocket的onMessage、onOpen、onClose、onError,其实就是websocket的事件
import java.net.URI;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
class WebSocketClientInst extends WebSocketClient {
public WebSocketClientInst(URI serverUri ) {
super( serverUri );
}
@Override
public void onOpen( ServerHandshake handshakedata ) {
System.out.println( "Connected" );
}
@Override
public void onMessage( String message ) {
System.out.println( "got: " + message );
}
@Override
public void onClose( int code, String reason, boolean remote ) {
System.out.println( "Disconnected" );
}
@Override
public void onError( Exception ex ) {
ex.printStackTrace();
}
}
然后就是wss的重头戏了,这里面的核心其实是SSLSocketFactory 和SSLSocket,感兴趣可以深入百度了解下:
import org.java_websocket.enums.ReadyState;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.net.URI;
import java.security.KeyStore;
class SSLClientExample {
public static void main( String[] args ) throws Exception {
WebSocketClientInst chatclient = new WebSocketClientInst( new URI( "wss://ip:port/test/path" ) );
// load up the key store
String KEYSTORE = "xx/xxxx/my.store"; //基于证书生成的store秘钥文件的路径
String STOREPASSWORD = "123456"; //使用keytool工具时,输入的密码
String KEYPASSWORD = "123456";
KeyStore ks = KeyStore.getInstance( KeyStore.getDefaultType() );
File kf = new File( KEYSTORE );
ks.load( new FileInputStream( kf ), STOREPASSWORD.toCharArray() );
KeyManagerFactory kmf = KeyManagerFactory.getInstance( "SunX509" );
kmf.init( ks, KEYPASSWORD.toCharArray() );
TrustManagerFactory tmf = TrustManagerFactory.getInstance( "SunX509" );
tmf.init( ks );
SSLContext sslContext = null;
sslContext = SSLContext.getInstance( "TLS" );
sslContext.init( kmf.getKeyManagers(), tmf.getTrustManagers(), null );
SSLSocketFactory factory = sslContext.getSocketFactory();// (SSLSocketFactory) SSLSocketFactory.getDefault();
chatclient.setSocketFactory( factory );
chatclient.connectBlocking();
boolean loop = true;
int times = 0;
while (loop){
times++;
if (ReadyState.OPEN.equals(chatclient.getReadyState())) {
chatclient.send(getBytes("a.wav")); //发送二进制文件
}else {
System.out.println("还没ready, 继续进行中");
if (times<=10) {
Thread.sleep(1000);
}else{
System.out.println("超时");
break;
}
}
}
}
public static byte[] getBytes(String filePath){
byte[] buffer = null;
try {
File file = new File(filePath);
FileInputStream fis = new FileInputStream(file);
ByteArrayOutputStream bos = new ByteArrayOutputStream(1000);
byte[] b = new byte[1000];
int n;
while ((n = fis.read(b)) != -1) {
bos.write(b, 0, n);
}
fis.close();
bos.close();
buffer = bos.toByteArray();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return buffer;
}
}
至此完成代码,你可以使用这个代码,然后实现jmeter的java sample,用来作压测了