使用倒推的方式
1. 要支持wss,其实就是在WebSocket中添加ssl。
2. 在netty中添加ssl的方式,就是在pipeline添加过滤器
pipeline.addLast(“ssl”, new SslHandler(engine));
3. 具体生成SslHandler需要SSLEngine
- SSLEngine.setUseClientMode设置(客户端或者服务器)模式
4. SSLEngine使用sslContext.createSSLEngine()方式创建
5. SSLContext就根据实际情况设置,需要的内容
- KeyStore.type 现在是使用jdk生成的JKS
- String path 证书路径
- String password 证书密码
6. 证书生成可以使用jdk的工具keytool
keytool -genkey -keysize 2048 -validity 365 -keyalg RSA -keypass netty123 -storepass netty123 -keystore wss.jks
# keytool -importkeystore -srckeystore wss.jks -destkeystore wss.jks -deststoretype pkcs12
keytool为JDK提供的生成证书工具
-keysize 2048 密钥长度2048位(这个长度的密钥目前可认为无法被暴力破解)
-validity 365 证书有效期365天
-keyalg RSA 使用RSA非对称加密算法
-dname "CN=localhost" 设置Common Name为localhost,域名
-keypass netty123 密钥的访问密码为netty123
-storepass netty123 密钥库的访问密码为netty123(其实这两个密码也可以设置一样,通常都设置一样,方便记)
-keystore wss.jks 指定生成的密钥库文件为wss.jks
SSLEngine sslEngine = null;
try {
//SSLEngine 此类允许使用ssl安全套接层协议进行安全通信
sslEngine = SSLContext.getDefault().createSSLEngine();
sslEngine.setUseClientMode(true);
pipeline.addLast("ssl", new SslHandler(sslEngine));
} catch (Exception e) {
e.printStackTrace();
}
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
try {
SSLContext sslContext = null;
// TODO 这里面的几项需要换成ServerConfig中的参数
sslContext = SslUtil.createSSLContext("JKS", "D:\\workdir\\doc\\jks\\wss.jks", "netty123");
// SSLEngine 此类允许使用ssl安全套接层协议进行安全通信
SSLEngine engine = sslContext.createSSLEngine();
// 服务器模式
engine.setUseClientMode(false);
//ssl双向认证
engine.setNeedClientAuth(false);
engine.setWantClientAuth(false);
// engine.setEnabledProtocols(new String[] { "SSLv3", "TLSv1" })
// TLSv1.2包括了SSLv3
engine.setEnabledProtocols(new String[] { "TLSv1.2" });
pipeline.addLast("ssl", new SslHandler(engine));
} catch (SSLException e) {
logger.debug("创建ssl出现错误", e);
}
2.创建SSLContext
/**
* 创建一个SSLContext
*
* @param type 类型
* @param path 路径
* @param password 密码
* @return SSLContext
* @throws Exception 返回里面的错误
*/
public static SSLContext createSSLContext(String type, String path, String password) throws SSLException {
KeyStore ks = null; /// "JKS"
SSLContext sslContext = null; /// "JKS"
try {
ks = KeyStore.getInstance(type);
InputStream ksInputStream = new FileInputStream(path); /// 证书存放地址
ks.load(ksInputStream, password.toCharArray());
//KeyManagerFactory充当基于密钥内容源的密钥管理器的工厂。
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());//getDefaultAlgorithm:获取默认的 KeyManagerFactory 算法名称。
kmf.init(ks, password.toCharArray());
//SSLContext的实例表示安全套接字协议的实现,它充当用于安全套接字工厂或 SSLEngine 的工厂。
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, null);
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException | NoSuchAlgorithmException | IOException | KeyManagementException e) {
throw new SSLException("create ssl find error "+e.getMessage());
}
return sslContext;
}
var websocket = new WebSocket("wss://127.0.0.1:8088");
websocket.onmessage = function(evt){
var data = evt.data;
alert("received message: " + data);
}
bootstrap.handler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) {
ChannelPipeline pipeline = ch.pipeline();
SSLEngine sslEngine = null;
try {
//SSLEngine 此类允许使用ssl安全套接层协议进行安全通信
sslEngine = SSLContext.getDefault().createSSLEngine();
sslEngine.setUseClientMode(true);
pipeline.addLast("ssl", new SslHandler(sslEngine));
} catch (Exception e) {
e.printStackTrace();
}
}
}
可以看这个
这次代码很快会被下一个版本覆盖,一些属性会使用配置文件进行输入
/*
* Copyright (C), 2015-2018
* FileName: SSLException
* Author: zhao
* Date: 2018/8/17 18:04
* Description: 添加ssl时发生的错误
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.base.exception;
/**
* 〈一句话功能简述〉<br>
* 〈添加ssl时发生的错误〉
*
* @author zhao
* @date 2018/8/17 18:04
* @since 1.0.1
*/
public class SSLException extends Exception {
private String errMsg;
public SSLException(String errMsg) {
super(errMsg);
this.errMsg = errMsg;
}
public SSLException(Throwable cause) {
super(cause);
}
}
/*
* Copyright (C), 2015-2018
* FileName: SslUtil
* Author: zhao
* Date: 2018/8/16 12:06
* Description: Ssl工具类
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.base.util;
import com.lizhaoblog.base.exception.SSLException;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
/**
* 〈一句话功能简述〉<br>
* 〈Ssl工具类〉
*
* @author zhao
* @date 2018/8/16 12:06
* @since 1.0.1
*/
public class SslUtil {
/**
* 创建一个SSLContext
*
* @param type 类型
* @param path 路径
* @param password 密码
* @return SSLContext
* @throws Exception 返回里面的错误
*/
public static SSLContext createSSLContext(String type, String path, String password) throws SSLException {
KeyStore ks = null; /// "JKS"
SSLContext sslContext = null; /// "JKS"
try {
ks = KeyStore.getInstance(type);
InputStream ksInputStream = new FileInputStream(path); /// 证书存放地址
ks.load(ksInputStream, password.toCharArray());
//KeyManagerFactory充当基于密钥内容源的密钥管理器的工厂。
KeyManagerFactory kmf = KeyManagerFactory
.getInstance(KeyManagerFactory.getDefaultAlgorithm());//getDefaultAlgorithm:获取默认的 KeyManagerFactory 算法名称。
kmf.init(ks, password.toCharArray());
//SSLContext的实例表示安全套接字协议的实现,它充当用于安全套接字工厂或 SSLEngine 的工厂。
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, null);
} catch (KeyStoreException | CertificateException | UnrecoverableKeyException | NoSuchAlgorithmException | IOException | KeyManagementException e) {
throw new SSLException("create ssl find error "+e.getMessage());
}
return sslContext;
}
static class miTM implements TrustManager, X509TrustManager {
public X509Certificate[] getAcceptedIssuers() {
return null;
}
public boolean isServerTrusted(X509Certificate[] certs) {
return true;
}
public boolean isClientTrusted(X509Certificate[] certs) {
return true;
}
public void checkServerTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
public void checkClientTrusted(X509Certificate[] certs, String authType) throws CertificateException {
return;
}
}
/**
* 忽略HTTPS请求的SSL证书,必须在openConnection之前调用
*
* @throws Exception
*/
public static void ignoreSsl() throws Exception {
HostnameVerifier hv = new HostnameVerifier() {
public boolean verify(String urlHostName, SSLSession session) {
System.out.println("Warning: URL Host: " + urlHostName + " vs. " + session.getPeerHost());
return true;
}
};
trustAllHttpsCertificates();
HttpsURLConnection.setDefaultHostnameVerifier(hv);
}
private static void trustAllHttpsCertificates() throws Exception {
TrustManager[] trustAllCerts = new TrustManager[1];
TrustManager tm = new miTM();
trustAllCerts[0] = tm;
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, trustAllCerts, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
}
}
/*
* Copyright (C), 2015-2018
* FileName: SSLCre
* Author: zhao
* Date: 2018/8/17 15:40
* Description: ssl
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.common;
/**
* 〈一句话功能简述〉<br>
* 〈ssl〉
*
* @author zhao
* @date 2018/8/17 15:40
* @since 1.0.1
* <p>
* Originally from:
* http://blogs.sun.com/andreas/resource/InstallCert.java
* Use:
* java InstallCert hostname
* Example:
* % java InstallCert ecc.fedora.redhat.com
* <p>
* Originally from:
* http://blogs.sun.com/andreas/resource/InstallCert.java
* Use:
* java InstallCert hostname
* Example:
* % java InstallCert ecc.fedora.redhat.com
* <p>
* Originally from:
* http://blogs.sun.com/andreas/resource/InstallCert.java
* Use:
* java InstallCert hostname
* Example:
* % java InstallCert ecc.fedora.redhat.com
*//*
* Copyright 2006 Sun Microsystems, Inc. All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Sun Microsystems nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/**
* Originally from:
* http://blogs.sun.com/andreas/resource/InstallCert.java
* Use:
* java InstallCert hostname
* Example:
*% java InstallCert ecc.fedora.redhat.com
*/
import javax.net.ssl.*;
import java.io.*;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
/**
* Class used to add the server's certificate to the KeyStore
* with your trusted certificates.
*/
public class SSLCre {
public static void main(String[] args) throws Exception {
String host = "127.0.0.1";
int port = 8088;
String passphraseStr = "changeit";
char[] passphrase = passphraseStr.toCharArray();
// if ((args.length == 1) || (args.length == 2)) {
// String[] c = args[0].split(":");
// host = c[0];
// port = (c.length == 1) ? 443 : Integer.parseInt(c[1]);
// String p = (args.length == 1) ? "changeit" : args[1];
// passphrase = p.toCharArray();
// } else {
// System.out.println("Usage: java InstallCert <host>[:port] [passphrase]");
// return;
// }
File file = new File("jssecacerts");
if (file.isFile() == false) {
char SEP = File.separatorChar;
File dir = new File(System.getProperty("java.home") + SEP + "lib" + SEP + "security");
file = new File(dir, "jssecacerts");
if (file.isFile() == false) {
file = new File(dir, "cacerts");
}
}
System.out.println("Loading KeyStore " + file + "...");
InputStream in = new FileInputStream(file);
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
ks.load(in, passphrase);
in.close();
SSLContext context = SSLContext.getInstance("TLS");
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(ks);
X509TrustManager defaultTrustManager = (X509TrustManager) tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init(null, new TrustManager[] { tm }, null);
SSLSocketFactory factory = context.getSocketFactory();
System.out.println("Opening connection to " + host + ":" + port + "...");
SSLSocket socket = (SSLSocket) factory.createSocket(host, port);
socket.setSoTimeout(10000);
try {
System.out.println("Starting SSL handshake...");
socket.startHandshake();
socket.close();
System.out.println();
System.out.println("No errors, certificate is already trusted");
} catch (SSLException e) {
System.out.println();
e.printStackTrace(System.out);
}
X509Certificate[] chain = tm.chain;
if (chain == null) {
System.out.println("Could not obtain server certificate chain");
return;
}
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
System.out.println();
System.out.println("Server sent " + chain.length + " certificate(s):");
System.out.println();
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
MessageDigest md5 = MessageDigest.getInstance("MD5");
for (int i = 0; i < chain.length; i++) {
X509Certificate cert = chain[i];
System.out.println(" " + (i + 1) + " Subject " + cert.getSubjectDN());
System.out.println(" Issuer " + cert.getIssuerDN());
sha1.update(cert.getEncoded());
System.out.println(" sha1 " + toHexString(sha1.digest()));
md5.update(cert.getEncoded());
System.out.println(" md5 " + toHexString(md5.digest()));
System.out.println();
}
System.out.println("Enter certificate to add to trusted keystore or 'q' to quit: [1]");
String line = reader.readLine().trim();
int k;
try {
k = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
} catch (NumberFormatException e) {
System.out.println("KeyStore not changed");
return;
}
X509Certificate cert = chain[k];
String alias = host + "-" + (k + 1);
ks.setCertificateEntry(alias, cert);
OutputStream out = new FileOutputStream("jssecacerts");
ks.store(out, passphrase);
out.close();
System.out.println();
System.out.println(cert);
System.out.println();
System.out.println("Added certificate to keystore 'jssecacerts' using alias '" + alias + "'");
}
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
private static String toHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes) {
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(' ');
}
return sb.toString();
}
private static class SavingTrustManager implements X509TrustManager {
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm) {
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers() {
/**
* This change has been done due to the following resolution advised for Java 1.7+
http://infposs.blogspot.kr/2013/06/installcert-and-java-7.html
**/
return new X509Certificate[0];
//throw new UnsupportedOperationException();
}
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
throw new UnsupportedOperationException();
}
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
this.chain = chain;
tm.checkServerTrusted(chain, authType);
}
}
}
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" charset="utf-8" >
window.WebSocket = window.WebSocket || window.MozWebSocket;
if (!window.WebSocket){
alert("WebSocket not supported by this browser");
}
var websocket = new WebSocket("wss://127.0.0.1:8088");
websocket.onmessage = function(evt){
var data = evt.data;
alert("received message: " + data);
}
function send() {
var name = document.getElementById('name').value;
alert("websocket send message:"+name);
websocket.send(name);
}
</script>
</head>
<body>
<label for="name">What’s your name:</label>
<input type="text" id="name" name="name" id='name'/>
<button onclick="send()">Send</button>
<div id="message" style="color:red"></div>
</body>
</html>
/*
* Copyright (C), 2015-2018
* FileName: WebSocketChannelInitializer
* Author: zhao
* Date: 2018/8/10 11:42
* Description: webSocket的channel
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.server.channel.websocket;
import com.lizhaoblog.base.exception.SSLException;
import com.lizhaoblog.base.message.codec.IMessageToWebSocketFrameEncoder;
import com.lizhaoblog.base.message.codec.WebSocketFrameToIMessageDecoder;
import com.lizhaoblog.base.util.SslUtil;
import com.lizhaoblog.server.pojo.ServerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
/**
* 〈一句话功能简述〉<br>
* 〈webSocket的channel〉
*
* @author zhao
* @date 2018/8/10 11:42
* @since 1.0.1
*/
@Component
public class WebSocketChannelInitializer extends ChannelInitializer<SocketChannel> {
private static final Logger logger = LoggerFactory.getLogger(WebSocketChannelInitializer.class);
@Override
protected void initChannel(SocketChannel ch) {
ChannelPipeline pipeline = ch.pipeline();
try {
SSLContext sslContext = null;
// TODO 这里面的几项需要换成ServerConfig中的参数
sslContext = SslUtil.createSSLContext("JKS", "D:\\workdir\\doc\\jks\\wss.jks", "netty123");
// SSLEngine 此类允许使用ssl安全套接层协议进行安全通信
SSLEngine engine = sslContext.createSSLEngine();
// 服务器模式
engine.setUseClientMode(false);
//ssl双向认证
engine.setNeedClientAuth(false);
engine.setWantClientAuth(false);
// engine.setEnabledProtocols(new String[] { "SSLv3", "TLSv1" })
// TLSv1.2包括了SSLv3
engine.setEnabledProtocols(new String[] { "TLSv1.2" });
pipeline.addLast("ssl", new SslHandler(engine));
} catch (SSLException e) {
logger.debug("创建ssl出现错误", e);
}
pipeline.addLast("http-codec", new HttpServerCodec()); // Http消息编码解码
pipeline.addLast("aggregator", new HttpObjectAggregator(65536)); // Http消息组装
pipeline.addLast("http-chunked", new ChunkedWriteHandler()); // WebSocket通信支持
// 消息编解码
pipeline.addLast("encoder", new IMessageToWebSocketFrameEncoder());
pipeline.addLast("decoder", new WebSocketFrameToIMessageDecoder());
WebSocketHandler webSocketHandler = (WebSocketHandler) ServerConfig.getInstance().getApplicationContext()
.getBean("webSocketHandler");
pipeline.addLast(webSocketHandler);
}
}
/*
* Copyright (C), 2015-2018
* FileName: WebSocketClientTest
* Author: zhao
* Date: 2018/8/2 17:32
* Description: websocket测试
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.server.channel.websocket;
import com.lizhaoblog.base.message.codec.IMessageToWebSocketFrameEncoder;
import com.lizhaoblog.base.message.codec.WebSocketFrameToIMessageDecoder;
import com.lizhaoblog.base.message.impl.ByteMessage;
import com.lizhaoblog.common.CommonValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.net.URI;
import java.net.URISyntaxException;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.http.DefaultHttpHeaders;
import io.netty.handler.codec.http.HttpClientCodec;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshaker;
import io.netty.handler.codec.http.websocketx.WebSocketClientHandshakerFactory;
import io.netty.handler.codec.http.websocketx.WebSocketVersion;
import io.netty.handler.ssl.SslHandler;
/**
* 〈一句话功能简述〉<br>
* 〈websocket测试〉
*
* @author zhao
* @date 2018/8/2 17:32
* @since 1.0.1
*/
public class WebSocketClientTest {
private static final Logger logger = LoggerFactory.getLogger(WebSocketClientTest.class);
private static EventLoopGroup group = new NioEventLoopGroup();
private static WebSocketClientHandlerTest handler;
private String uriStr = "wss//" + CommonValue.IP + ":" + CommonValue.PORT;
public void run() throws InterruptedException, URISyntaxException {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(group);
bootstrap.channel(NioSocketChannel.class);
// 主要是为handler(自己写的类)服务
URI wsUri = new URI(uriStr);
WebSocketClientHandshaker webSocketClientHandshaker = WebSocketClientHandshakerFactory
.newHandshaker(wsUri, WebSocketVersion.V13, null, true, new DefaultHttpHeaders(), 100 * 1024 * 1024);
handler = new WebSocketClientHandlerTest(webSocketClientHandshaker);
bootstrap.handler(new ChannelInitializer() {
@Override
protected void initChannel(Channel ch) {
ChannelPipeline pipeline = ch.pipeline();
SSLEngine sslEngine = null;
try {
//SSLEngine 此类允许使用ssl安全套接层协议进行安全通信
sslEngine = SSLContext.getDefault().createSSLEngine();
sslEngine.setUseClientMode(true);
pipeline.addLast("ssl", new SslHandler(sslEngine));
} catch (Exception e) {
e.printStackTrace();
}
pipeline.addLast(new HttpClientCodec());
pipeline.addLast(new HttpObjectAggregator(65536));
pipeline.addLast("encoder", new IMessageToWebSocketFrameEncoder());
pipeline.addLast("decoder", new WebSocketFrameToIMessageDecoder());
// pipeline.addLast("encoder", new MessageEncoder());
// pipeline.addLast("decoder", new MessageDecoder(ConstantValue.MESSAGE_CODEC_MAX_FRAME_LENGTH,
// ConstantValue.MESSAGE_CODEC_LENGTH_FIELD_LENGTH, ConstantValue.MESSAGE_CODEC_LENGTH_FIELD_OFFSET,
// ConstantValue.MESSAGE_CODEC_LENGTH_ADJUSTMENT, ConstantValue.MESSAGE_CODEC_INITIAL_BYTES_TO_STRIP,
// false, ServerConfig.getInstance().getMessageType()));
pipeline.addLast(handler);
}
});
ByteMessage byteMessage = new ByteMessage();
byteMessage.setMessageId(com.lizhaoblog.server.biz.constant.CommonValue.CM_MSG_TEST_BYTE);
byteMessage.setStatusCode(com.lizhaoblog.server.biz.constant.CommonValue.MSG_STATUS_CODE_SUCCESS);
byteMessage.addAttr(2);
// 连接服务端
// ChannelFuture channelFuture = bootstrap.connect(CommonValue.IP, CommonValue.PORT).sync();
ChannelFuture channelFuture = bootstrap.connect(CommonValue.IP, CommonValue.PORT).sync();
handler.handshakeFuture().sync();
// channelFuture.channel().writeAndFlush(byteMessage);
// WebSocketFrame frame = new PingWebSocketFrame(Unpooled.wrappedBuffer(new byte[] { 8, 1, 8, 1 }));
// WebSocketFrame frame = new TextWebSocketFrame("aaa");
// channelFuture.channel().writeAndFlush(frame);
byte[] bytes = new byte[14];
bytes[0] = 0;
bytes[1] = 1;
bytes[2] = 0;
bytes[3] = 1;
bytes[4] = 0;
bytes[5] = 0;
bytes[6] = 0;
bytes[7] = 6;
bytes[8] = 2;
bytes[9] = 0;
bytes[10] = 0;
bytes[11] = 0;
bytes[12] = 0;
bytes[13] = 1;
channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer(bytes));
BinaryWebSocketFrame frame = new BinaryWebSocketFrame(Unpooled.copiedBuffer(bytes));
// channelFuture.channel().writeAndFlush(frame);
channelFuture.channel().writeAndFlush(byteMessage);
logger.info("向Socket服务器发送数据:" + byteMessage);
channelFuture.channel().closeFuture().sync();
}
}
/*
* Copyright (C), 2015-2018
* FileName: NettyClientTest
* Author: zhao
* Date: 2018/6/12 15:34
* Description: NettyClient的测试数据
* History:
* <author> <time> <version> <desc>
* 作者姓名 修改时间 版本号 描述
*/
package com.lizhaoblog.server.channel;
import com.lizhaoblog.base.util.SslUtil;
import com.lizhaoblog.server.channel.tcp.bytec.TcpByteClientTest;
import com.lizhaoblog.server.channel.tcp.str.TcpStringClientTest;
import com.lizhaoblog.server.channel.websocket.WebSocketClientTest;
import com.lizhaoblog.server.pojo.ServerConfig;
import org.junit.Before;
import org.junit.Test;
import java.net.URISyntaxException;
/**
* 〈一句话功能简述〉<br>
* 〈NettyClient的测试数据〉
*
* @author zhao
* @date 2018/6/12 15:34
* @since 1.0.0
*/
public class NettyClientTest {
@Before
public void init() {
ServerConfig.getInstance().init();
ServerConfig.getInstance().setMessageType("STRING");
}
@Test
public void testTcpStringClient() throws InterruptedException {
TcpStringClientTest tcpStringClientTest = new TcpStringClientTest();
tcpStringClientTest.run();
}
@Test
public void testTcpByteClient() throws InterruptedException {
ServerConfig.getInstance().setMessageType("BYTE");
TcpByteClientTest tcpByteClientTest = new TcpByteClientTest();
tcpByteClientTest.run();
}
@Test
public void testWebSocketByteClient() throws InterruptedException, URISyntaxException,Exception {
SslUtil.ignoreSsl();
ServerConfig.getInstance().setMessageType("BYTE");
WebSocketClientTest webSocketClientTest = new WebSocketClientTest();
webSocketClientTest.run();
}
}
上面的代码在码云上 https://gitee.com/lizhaoandroid/JgServer 以加qq群一起探讨Java游戏服务器开发的相关知识 676231564