JAVA模拟WebSocket客户端,支持wss ssl证书

背景:websocket在Html5里面有着举足轻重的地位,最近工作中需要对websocket接口进行压测,使用jmeter的websocket
sample进行,但是一般现网的websocket都是采用的wss://协议,直接使用ws://协议的较少,毕竟安全还是非常重要的,这里就涉及到ssl协议,模拟websocket客户端,使用证书和公钥,摸索了半天终于摸索出来了。

java websocket client

java 中模拟websocket client请参考 https://github.com/TooTallNate/Java-WebSocket, 里面有非常详细的说明。

maven项目中引入


  org.java-websocket
  Java-WebSocket
  1.4.0

然后参考 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,用来作压测了

你可能感兴趣的:(java)