一、Netty服务端
1、NettyServer
2、NettyServerChannelInitializer
3、NettyServerHandler
如何启动?
package web
import com.hbscTools.NettyServer
import grails.boot.GrailsApp
import grails.boot.config.GrailsAutoConfiguration
class Application extends GrailsAutoConfiguration {
static void main(String[] args) {
GrailsApp.run(Application, args)
//初始化netty
NettyServer nettyServer = new NettyServer();
nettyServer.bind();
}
}
如何使用?
//服务器推送消息至指定客户端
NettyServerHandler.sendMsg2Client(机器编号, 消息体)
.addListener({ future ->//异步监听发送结果
})
//服务器群发消息至所有在线客户端
//还没写,等有需要再写!
...
...
...
心跳包机制
@Override
public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
if (evt instanceof IdleStateEvent) {
IdleStateEvent event = (IdleStateEvent) evt;
if (event.state().equals(IdleState.READER_IDLE)) {
// 空闲40s之后触发 (心跳包丢失)
Integer counter = online_channels_heart.get(ctx.channel().id().asLongText());
if (counter >= 3) {
// 连续丢失3个心跳包 (断开连接)
ctx.channel().close().sync();
System.out.println("已与" + ctx.channel().remoteAddress() + "断开连接");
} else {
counter++;
//重置心跳丢失次数
online_channels_heart.replace(ctx.channel().id().asLongText(), counter);
System.out.println("丢失了第 " + counter + " 个心跳包");
}
}
}
}
TCP粘包与分包处理
ChannelPipeline pipeline = ch.pipeline();
//解决TCP粘包拆包的问题,以特定的字符结尾($_)
pipeline.addLast(new DelimiterBasedFrameDecoder(Integer.MAX_VALUE, Unpooled.copiedBuffer("$_".getBytes())));
相关代码
package com.hbscTools;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
* author : ZZL(周子林)
* e-mail : 349709285@qq.com
* date : 2019/12/17 16:37
* desc :
* version: 1.0
*/
public class NettyServer {
private int port = 8888;
private NettyServerChannelInitializer serverChannelInitializer = null;
public void bind() throws Exception {
//配置服务端的NIO线程组
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
serverChannelInitializer = new NettyServerChannelInitializer();
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
//保持长连接
.childOption(ChannelOption.SO_KEEPALIVE, true)
.option(ChannelOption.SO_BACKLOG, 10