
Springboot项目的web服务后台,web服务运行在9100端口。
后台使用netty实现了TCP服务,运行在8000端口。
启动截图如下:
netty服务代码import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
public class NettyServer {
private final int port; //监听端口
public NettyServer(int port) {
this.port = port;
}
//编写run方法,处理客户端的请求
public void run() throws Exception {
//创建两个线程组
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup(); //8个NioEventLoop
try {
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//获取到pipeline
ChannelPipeline pipeline = ch.pipeline();
//向pipeline加入解码器
pipeline.addLast("decoder", new StringDecoder());
//向pipeline加入编码器
pipeline.addLast("encoder", new StringEncoder());
//加入自己的业务处理handler
pipeline.addLast(new NettyServerHandler());
}
});
System.out.println("netty服务器启动成功(port:" + port + ")......");
ChannelFuture channelFuture = b.bind(port).sync();
//监听关闭
channelFuture.channel().closeFuture().sync();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
netty业务处理handler
import io.netty.channel.Channel; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.util.concurrent.GlobalEventExecutor; import lombok.extern.slf4j.Slf4j; @Slf4j public class NettyServerHandler extends SimpleChannelInboundHandlerSpringboot项目中启动netty服务{ //定义一个channle 组,管理所有的channel //GlobalEventExecutor.INSTANCE) 是全局的事件执行器,是一个单例 public static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); @Override public void handlerAdded(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); System.err.println("有新的客户端与服务器发生连接。客户端地址:" + channel.remoteAddress()); channelGroup.add(channel); } @Override public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { Channel channel = ctx.channel(); System.err.println("有客户端与服务器断开连接。客户端地址:" + channel.remoteAddress()); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress() + " 处于活动状态"); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { System.out.println(ctx.channel().remoteAddress() + " 处于不活动状态"); } @Override protected void channelRead0(ChannelHandlerContext ctx, String msg) { //获取到当前channel Channel channel = ctx.channel(); System.err.println("有客户端发来的数据。地址:" + channel.remoteAddress() + " 内容:" + msg); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { log.error("发生异常。异常信息:{}", cause.getMessage()); //关闭通道 ctx.close(); } }
启动类修改:
测试结果截图 服务启动,及客户端连接 客户端给服务器发送数据 服务器给客户端发送数据 服务器查看当前所有连接的客户端服务器获取到所有客户单的ip地址及端口号后,即可通过其给指定客户端发送数据