目录
在上一套写法方案,将 SslContext 创建的时候只创建一次,省去每次调用每次创建
介绍
本地开发用localhost 127.0.0.1 和ws 的方法即可
切换到服务端就要调整了,或本地其他人访问也要调整
域内换可以修改window下的hosts文件 加个 127.0.0.1 域名 或 对方域内ip 域名
去各类云服务器申请域名和ssl 域内开发可以先设置hosts文件 不是域内直接配置服务器即可
最近把项目挂出去,和其他前端使用 所以要调整,从127 改成 域名,让外部也可访问,改种发现一车bug 有需要的可以看看
修改本地该hosts 文件
系统盘:C:\Windows\System32\drivers\etc\hosts
地址截图
修改截图
提示
windows 很多,没这么多东西 都是空的,直接在下边加
127.0.0.1 自定义域名
或其他ip 自定义域名即可
先看各类bug就不介绍bug啥意思了,一艘好多介绍的
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
netty URL“wss//192.168.8.109:9999/ws”无效。
test.html:39 WebSocket connection to 'wss://ma.yueduixiang.com:9999/ws' failed: Error in connection establishment: net::ERR_CONNECTION_CLOSED
15:45:17.585 [nioEventLoopGroup-3-1] WARN io.netty.channel.ChannelInitializer - Failed to initialize a channel. Closing: [id: 0x04cb96ee, L:/127.0.0.1:9999 - R:/127.0.0.1:56833]
java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:780)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
at java.security.KeyStore.load(KeyStore.java:1445)
at com.superman.nettyim.SslUtil.createSSLContext(SslUtil.java:35)
at com.superman.nettyim.IMNettyServerInitialzer.initChannel(IMNettyServerInitialzer.java:44)
at com.superman.nettyim.IMNettyServerInitialzer.initChannel(IMNettyServerInitialzer.java:1)
at io.netty.channel.ChannelInitializer.initChannel(ChannelInitializer.java:115)
at io.netty.channel.ChannelInitializer.handlerAdded(ChannelInitializer.java:107)
at io.netty.channel.DefaultChannelPipeline.callHandlerAdded0(DefaultChannelPipeline.java:637)
at io.netty.channel.DefaultChannelPipeline.access$000(DefaultChannelPipeline.java:46)
at io.netty.channel.DefaultChannelPipeline$PendingHandlerAddedTask.execute(DefaultChannelPipeline.java:1487)
at io.netty.channel.DefaultChannelPipeline.callHandlerAddedForAllHandlers(DefaultChannelPipeline.java:1161)
at io.netty.channel.DefaultChannelPipeline.invokeHandlerAddedIfNeeded(DefaultChannelPipeline.java:686)
at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:514)
at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:427)
at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:486)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:474)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:909)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.UnrecoverableKeyException: Password verification failed
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:778)
... 23 common frames omitted
15:45:17.602 [nioEventLoopGroup-3-2] WARN io.netty.channel.ChannelInitializer - Failed to initialize a channel. Closing: [id: 0x81b2235f, L:/127.0.0.1:9999 - R:/127.0.0.1:56837]
java.io.IOException: Keystore was tampered with, or password was incorrect
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:780)
at sun.security.provider.JavaKeyStore$JKS.engineLoad(JavaKeyStore.java:56)
at sun.security.provider.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:224)
at sun.security.provider.JavaKeyStore$DualFormatJKS.engineLoad(JavaKeyStore.java:70)
at java.security.KeyStore.load(KeyStore.java:1445)
at com.superman.nettyim.SslUtil.createSSLContext(SslUtil.java:35)
at com.superman.nettyim.IMNettyServerInitialzer.initChannel(IMNettyServerInitialzer.java:44)
at com.superman.nettyim.IMNettyServerInitialzer.initChannel(IMNettyServerInitialzer.java:1)
at io.netty.channel.ChannelInitializer.initChannel(ChannelInitializer.java:115)
at io.netty.channel.ChannelInitializer.handlerAdded(ChannelInitializer.java:107)
at io.netty.channel.DefaultChannelPipeline.callHandlerAdded0(DefaultChannelPipeline.java:637)
at io.netty.channel.DefaultChannelPipeline.access$000(DefaultChannelPipeline.java:46)
at io.netty.channel.DefaultChannelPipeline$PendingHandlerAddedTask.execute(DefaultChannelPipeline.java:1487)
at io.netty.channel.DefaultChannelPipeline.callHandlerAddedForAllHandlers(DefaultChannelPipeline.java:1161)
at io.netty.channel.DefaultChannelPipeline.invokeHandlerAddedIfNeeded(DefaultChannelPipeline.java:686)
at io.netty.channel.AbstractChannel$AbstractUnsafe.register0(AbstractChannel.java:514)
at io.netty.channel.AbstractChannel$AbstractUnsafe.access$200(AbstractChannel.java:427)
at io.netty.channel.AbstractChannel$AbstractUnsafe$1.run(AbstractChannel.java:486)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:474)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:909)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.security.UnrecoverableKeyException: Password verification failed
at sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:778)
... 23 common frames omitted
test.html:39 WebSocket connection to 'wss://ma.yueduixiang.com:9999/ws' failed: Error in connection establishment: net::ERR_CERT_AUTHORITY_INVALID
15:46:33.159 [nioEventLoopGroup-3-1] WARN io.netty.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:472)
at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:278)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1434)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:965)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:656)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:591)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:508)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:470)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:909)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634)
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1083)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:907)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:295)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1301)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1203)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1247)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:441)
... 16 common frames omitted
15:46:33.160 [nioEventLoopGroup-3-1] WARN io.netty.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.codec.DecoderException: javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:472)
at io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:405)
at io.netty.handler.codec.ByteToMessageDecoder.channelInputClosed(ByteToMessageDecoder.java:372)
at io.netty.handler.codec.ByteToMessageDecoder.channelInactive(ByteToMessageDecoder.java:355)
at io.netty.handler.ssl.SslHandler.channelInactive(SslHandler.java:1054)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231)
at io.netty.channel.AbstractChannelHandlerContext.fireChannelInactive(AbstractChannelHandlerContext.java:224)
at io.netty.channel.DefaultChannelPipeline$HeadContext.channelInactive(DefaultChannelPipeline.java:1429)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:245)
at io.netty.channel.AbstractChannelHandlerContext.invokeChannelInactive(AbstractChannelHandlerContext.java:231)
at io.netty.channel.DefaultChannelPipeline.fireChannelInactive(DefaultChannelPipeline.java:947)
at io.netty.channel.AbstractChannel$AbstractUnsafe$8.run(AbstractChannel.java:826)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:404)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:474)
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:909)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: javax.net.ssl.SSLException: Received fatal alert: certificate_unknown
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1666)
at sun.security.ssl.SSLEngineImpl.fatal(SSLEngineImpl.java:1634)
at sun.security.ssl.SSLEngineImpl.recvAlert(SSLEngineImpl.java:1800)
at sun.security.ssl.SSLEngineImpl.readRecord(SSLEngineImpl.java:1083)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:907)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:295)
at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1301)
at io.netty.handler.ssl.SslHandler.decodeJdkCompatible(SslHandler.java:1203)
at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1247)
at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:502)
at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:441)
... 18 common frames omitted
客户端断开,channle对应的长id为:005056fffec00001-00003328-00000001-371e6fb621ac9d11-9b925be2
客户端断开,channle对应的短id为:9b925be2
一套ok好方案
介绍
/**
* 初始化类
* netty 配置ssl 踩坑记录 最安全的一套方案 ,页面 访问后台,要用
* 1.页面 wss://(阿里云或腾讯云申请的ssl 域名地址 )/port/ws
* 2.服务端,配置域名使用申请下来的ssl 的jks 配置到 初始化类里
* 3.启动即可
* 4如果不安上边方法,很多种时候会出现 域名不正确,或不让连接,域名密码异常jks 和域名不匹配等一系列杂乱问题,
* 5.所以使用上边这套方案就好了
* 6.如果想,不要每次初始化类,可以吧初始化sslcontext 放出来,不要每次调用即可
* 7.ok
*
* @author jianghy
*
* @version 1.0
*/
初始化类加上这个
主要就这段代码
String jksPath = (System.getProperty("user.dir")+ "/target/classes/ssl/test/ma.yueduixiang.com.jks");
SSLContext sslContext = SslUtil.createSSLContext("JKS",jksPath,"ma.yueduixiang.com");
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setNeedClientAuth(false);
sslEngine.setUseClientMode(false);
pipeline.addLast("sslHandler", new SslHandler(sslEngine));
截图效果
初始化类型全代码
package com.superman.nettyim;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
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.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
/**
* 初始化类
* netty 配置ssl 踩坑记录 最安全的一套方案 ,页面 访问后台,要用
* 1.页面 wss://(阿里云或腾讯云申请的ssl 域名地址 )/port/ws
* 2.服务端,配置域名使用申请下来的ssl 的jks 配置到 初始化类里
* 3.启动即可
* 4如果不安上边方法,很多种时候会出现 域名不正确,或不让连接,域名密码异常jks 和域名不匹配等一系列杂乱问题,
* 5.所以使用上边这套方案就好了
* 6.如果想,不要每次初始化类,可以吧初始化sslcontext 放出来,不要每次调用即可
* 7.ok
*
* @author jianghy
*
* @version 1.0
*/
public class IMNettyServerInitialzer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
String jksPath = (System.getProperty("user.dir")+ "/target/classes/ssl/test/ma.yuedxuixiang.com.jks");
SSLContext sslContext = SslUtil.createSSLContext("JKS",jksPath,"ma.yueduixxiangozm");
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setNeedClientAuth(false);
sslEngine.setUseClientMode(false);
pipeline.addLast("sslHandler", new SslHandler(sslEngine));
ch.pipeline().addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS));
// websocket 基于http协议,所以要有http编解码器
pipeline.addLast(new HttpServerCodec());
// // 对写大数据流的支持
pipeline.addLast(new ChunkedWriteHandler());
// // 对httpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse
// // 几乎在netty中的编程,都会使用到此hanler
pipeline.addLast(new HttpObjectAggregator(1024*64));
// ====================== 以上是用于支持http协议 ======================
// ====================== 以下是支持httpWebsocket ======================
/**
* websocket 服务器处理的协议,用于指定给客户端连接访问的路由 : /ws
* 本handler会帮你处理一些繁重的复杂的事
* 会帮你处理握手动作: handshaking(close, ping, pong) ping + pong = 心跳
* 对于websocket来讲,都是以frames进行传输的,不同的数据类型对应的frames也不同
*/
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
// 自定义的handler
pipeline.addLast(new IMNettyHandler());
}
}
创建 SslUtil类
package com.superman.nettyim;
import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
/**
* 创建ssl 上下文
*
* @author jianghy
*
* @version 1.0
*/
public class SslUtil {
private static volatile SSLContext sslContext = null;
/**
* 创建
* @param type 类型(JKS)
* @param path JKS文件路径
* @param password jks 密码
* @return
* @throws Exception
*/
public static SSLContext createSSLContext(String type ,String path ,String password) throws Exception {
if(null == sslContext){
synchronized (SslUtil.class) {
if(null == sslContext){
// 支持JKS、PKCS12(我们项目中用的是阿里云免费申请的证书,下载tomcat解压后的pfx文件,对应PKCS12)
KeyStore ks = KeyStore.getInstance(type);
// 证书存放地址
InputStream ksInputStream = new FileInputStream(path);
ks.load(ksInputStream, password.toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, password.toCharArray());
sslContext = SSLContext.getInstance("TLS");
sslContext.init(kmf.getKeyManagers(), null, null);
}
}
}
return sslContext;
}
}
页面code
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<h3>在线客服</h3>
<p>
发送人id: <input type="text" id="msg0" value="1001"/><br />
发送人token:<input type="text" id="msg1" value="101"/><br />
收信人类型:<input type="text" id="msg2" value="1" /><br />
收信人id:<input type="text" id="msg3" value="1002"/><br />
信息:<input type="text" id="msg4" value="好帅"/><br />
<input type="button" value="点我发送" onclick="CHAT.chat()" />
</p>
<div>消息:</div>
<div id="receiveMsg" style="background-color: gainsboro;"></div>
<script type="application/javascript">
window.CHAT = {
socket: null,
init: function () {
if (window.WebSocket) {
var socketAddress = "wss://ma.yueduixiang.com:9999/ws";
CHAT.socket = new WebSocket(socketAddress);
CHAT.socket.onopen = function () {
console.log("连接建立成功...");
},
CHAT.socket.onclose = function () {
console.log("连接关闭...");
},
CHAT.socket.onerror = function () {
console.log("发生错误...");
},
CHAT.socket.onmessage = function (e) {
console.log("接受到消息:" + e.data);
var receiveMsg = document.getElementById("receiveMsg");
var html = receiveMsg.innerHTML;
receiveMsg.innerHTML = html + "<br/>" + "接受到消息:" + e.data;
}
} else {
alert("浏览器不支持websocket协议...");
}
},
chat: function () {
var msg0 = document.getElementById("msg0").value;
var msg1 = document.getElementById("msg1").value;
var msg2 = document.getElementById("msg2").value;
var msg3 = document.getElementById("msg3").value;
var msg4 = document.getElementById("msg4").value;
CHAT.socket.send(msg0 + "," + msg1 + "," + msg2 + "," + msg3 + "," + msg4);
var receiveMsg = document.getElementById("receiveMsg");
var html = receiveMsg.innerHTML;
receiveMsg.innerHTML = html + "<br/>" + "发送消息:" + msg4;
}
};
CHAT.init();
</script>
</body>
</html>
主要是这个
var socketAddress = "wss://ma.yueduixiang.com:9999/ws";
申请ssl
搭建详细框架看我这片博客
除了 ssluitl 没有和 初始化类加了几行代码,还有页面修改了ws 改成 wss://域名:port/ws 剩下都一样
yushen.blog.csdn.net/article/det…
ok
持续更新
在上一套写法方案,将 SslContext 创建的时候只创建一次,省去每次调用每次创建
启动类型
package com.superman.nettyim;
import javax.net.ssl.SSLContext;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
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.stream.ChunkedWriteHandler;
/**
* 及时通讯服务端
*
* @author jianghy
*
* @version 1.0
*/
public class IMNettyServer {
private int port = 8088;
public IMNettyServer(int port) {
this.port = port;
}
public void run() throws Exception {
String jksPath = (System.getProperty("user.dir")+ "/target/classes/ssl/test/ma.yuedasuixisaang.com.jks");
SSLContext sslContext = SslUtil.createSSLContext("JKS",jksPath,"ma.yasueduixasiang.com");
EventLoopGroup bossGroup = new NioEventLoopGroup(); // (1)
EventLoopGroup workerGroup = new NioEventLoopGroup();
System.out.println("----------------- netty Server Start--------------------");
try {
ServerBootstrap b = new ServerBootstrap(); // (2)
b.group(bossGroup, workerGroup)
//在这里,我们指定使用NioServerSocketChannel用于实例化新的类Channel以接受传入的连接。
.channel(NioServerSocketChannel.class) // (3)
.childHandler(new IMNettyServerInitialzer(sslContext))
.option(ChannelOption.SO_BACKLOG, 128) // (5)
.childOption(ChannelOption.SO_KEEPALIVE, true); // (6)
ChannelFuture f = b.bind(port).sync(); // (7)
System.out.println("-------------------netty server port:"+port+" start success -----------");
// 等待服务器套接字关闭。
//在本例中,这种情况不会发生,但您可以这样做
//优雅地
//关闭服务器。
f.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
new IMNettyServer(9999).run();
}
}
初始化类型
package com.superman.nettyim;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
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.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.ssl.SslHandler;
import io.netty.handler.stream.ChunkedWriteHandler;
import io.netty.handler.timeout.IdleStateHandler;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
/**
* 初始化类
* netty 配置ssl 踩坑记录 最安全的一套方案 ,页面 访问后台,要用
* 1.页面 wss://(阿里云或腾讯云申请的ssl 域名地址 )/port/ws
* 2.服务端,配置域名使用申请下来的ssl 的jks 配置到 初始化类里
* 3.启动即可
* 4如果不安上边方法,很多种时候会出现 域名不正确,或不让连接,域名密码异常jks 和域名不匹配等一系列杂乱问题,
* 5.所以使用上边这套方案就好了
* 6.如果想,不要每次初始化类,可以吧初始化sslcontext 放出来,不要每次调用即可
* 7.ok
*
* @author jianghy
*
* @version 1.0
*/
public class IMNettyServerInitialzer extends ChannelInitializer<SocketChannel> {
private SSLContext sslContext;
public IMNettyServerInitialzer(SSLContext sslContext){
this.sslContext = sslContext;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
// String jksPath = (System.getProperty("user.dir")+ "/target/classes/ssl/test/ma.yudedzuixiang.com.jks");
// SSLContext sslContext = SslUtil.createSSLContext("JKS",jksPath,"ma.yuedauisxiang.com");
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setNeedClientAuth(false);
sslEngine.setUseClientMode(false);
pipeline.addLast("sslHandler", new SslHandler(sslEngine));
ch.pipeline().addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS));
// websocket 基于http协议,所以要有http编解码器
pipeline.addLast(new HttpServerCodec());
// // 对写大数据流的支持
pipeline.addLast(new ChunkedWriteHandler());
// // 对httpMessage进行聚合,聚合成FullHttpRequest或FullHttpResponse
// // 几乎在netty中的编程,都会使用到此hanler
pipeline.addLast(new HttpObjectAggregator(1024*64));
// ====================== 以上是用于支持http协议 ======================
// ====================== 以下是支持httpWebsocket ======================
/**
* websocket 服务器处理的协议,用于指定给客户端连接访问的路由 : /ws
* 本handler会帮你处理一些繁重的复杂的事
* 会帮你处理握手动作: handshaking(close, ping, pong) ping + pong = 心跳
* 对于websocket来讲,都是以frames进行传输的,不同的数据类型对应的frames也不同
*/
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
pipeline.addLast(new StringDecoder());
pipeline.addLast(new StringEncoder());
pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
// 自定义的handler
pipeline.addLast(new IMNettyHandler());
}
}
ok
持续更新