「这是我参与11月更文挑战的第6天,活动详情查看:2021最后一次更文挑战」
服务端要求,欢迎给我留言和讨论
服务端会暴露在公网中,因此链接的安全性需要考虑。
防止数据篡改,和垃圾数据
走wss路线
mkcert测试证书生成
mkcert -p12-file keystore.p12 -pkcs12 192.168.0.103 127.0.0.1 localhost
默认配置`alias=1`, `password=changeit`
wss配置
//这里面的配置接受内容的长度过长,是因为当时做了写音视频编码为base64的转发
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new IdleStateHandler(10, 0, 0, TimeUnit.SECONDS));
pipeline.addLast(new HttpServerCodec());
pipeline.addLast(new HttpObjectAggregator(1024 * 1024));
pipeline.addLast(new ChunkedWriteHandler());
pipeline.addLast(new WebSocketServerProtocolHandler("/ws", null, true, 1024 * 512));
pipeline.addLast(new TextWebSocketFrameHandler());
// 配置ssl访问的
SSLContext sslContext = SslUtil.createSSLContext("PKCS12",
this.getClass().getClassLoader().getResourceAsStream("keystore.p12"), "changeit"); //
SSLEngine engine =sslContext.createSSLEngine();
SSLEngine sslEngine = sslContext.createSSLEngine();
sslEngine.setNeedClientAuth(false);
sslEngine.setUseClientMode(false);
pipeline.addFirst(new SslHandler(sslEngine));
}
新用户绑定验证
绑定的时候需要验证一下
这里用redis做了个缓存并加个过期时间:用户编码:token
这里登陆的是从其他服务登陆的,登录后会给创建个token缓存在redis用来共享
老用户验证
服务端保存的有长连接通道:用户名:链接通道
private static Map<ChartUser, Channel> userChannel = new ConcurrentHashMap <ChartUser, Channel>();
可以查看服务端链接的通道是否属于这个用户的,不然拒绝
断线重连
链接断开服务端会有个监听事件,移除链接
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
Channel incoming = ctx.channel();
logger.info("Client:" + incoming.remoteAddress() + "掉线");
ChannelManager.removeChannelByChannel(incoming);
}
前端这里以websocketd为例会触发ws.onclose方法
比如当前链接的服务端挂掉了,或者网络原因这里会触发这个方法
在这个方法里面我们依旧是从业务端1.获取tokenn
2.获取server的地址(ip+端口) 这里需要服务端做集群保证服务不断
3.重新绑定websocket服务端完成重连
4.失败可以添加重试次数