netty 客户端与服务端之间通信问题:客户端接收不到数据

问题出现:客户端能够发送消息至服务端,服务端广播的消息在客户端接收不到

Client端

public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        socketChannel.pipeline()
                .addLast(new TankJoinMsgEncoder())  // 客户端通过编码发送至服务端
                .addLast(new TankJoinMsgDecoder())  // 服务端解码服务端广播的消息
                .addLast(new ClientHandler()); 
    }
}
class ClientHandler extends SimpleChannelInboundHandler<TankJoinMsg> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TankJoinMsg msg) throws Exception {
        if(msg.id.equals(TankFrame.INSTANCE.getMainTank().getId()) ||
                TankFrame.INSTANCE.findByUUID(msg.id)!=null ) return;
        System.out.println(msg);
        Tank t = new Tank(msg);
        TankFrame.INSTANCE.addTank(t);
        ctx.writeAndFlush(new TankJoinMsg(TankFrame.INSTANCE.getMainTank())); // 发送消息至server端
    }
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.writeAndFlush(new TankJoinMsg(TankFrame.INSTANCE.getMainTank()));// 会通过TankJoinMsgEncoder编码,编完之后才会写到服务器
    }
}

Server端

public static ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

public void serverStart() {
        EventLoopGroup bossGroup = new NioEventLoopGroup(1); 
        EventLoopGroup workerGroup = new NioEventLoopGroup(2);

        ServerBootstrap sb = new ServerBootstrap(); // 辅助启动类
        try {
            ChannelFuture f = sb.group(bossGroup,workerGroup) // 指定线程池组
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pl = socketChannel.pipeline();
                            pl.addLast(new TankJoinMsgDecoder())
                                .addLast(new ServerChildHandler());
                        }
                    })
                    .bind(9999)
                    .sync();
            ServerFrame.INSTANCE.updateServerMsg("server started!");
            f.channel().closeFuture().sync(); // close->ChannelFuture
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }
class ServerChildHandler extends ChannelInboundHandlerAdapter{
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Server.clients.add(ctx.channel());
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        // 删除出现异常的客户端channel,并关闭连接
        Server.clients.remove(ctx.channel());
        ctx.close();
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ServerFrame.INSTANCE.updateClientMsg(msg.toString());
        Server.clients.writeAndFlush(msg);
    }
}

通过一番检查,才发现原因是在Server端下没有增加消息编码,导致Client端无法接收到数据
处理方法:

ChannelFuture f = sb.group(bossGroup,workerGroup) // 指定线程池组
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pl = socketChannel.pipeline();
                            pl.addLast(new TankJoinMsgDecoder())
                                .addLast(new TankJoinMsgEncoder()) // 该位置加上消息编码
                                .addLast(new ServerChildHandler());
                        }
                    })
                    .bind(9999)
                    .sync();
  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 16
    评论
Netty 中,客户端服务端发送数据需要经过以下步骤: 1. 创建一个 Bootstrap 实例,用于启动客户端。 2. 设置客户端的 EventLoopGroup,用于处理网络事件。 3. 配置客户端的 Channel,包括 Channel 的类型、ChannelPipeline 的配置等。 4. 连接到服务端,使用 connect() 方法连接到服务端。 5. 在连接成功后,向服务端发送数据,可以通过 ChannelHandlerContext 的 writeAndFlush() 方法实现。 以下是一个简单的示例代码: ```java EventLoopGroup group = new NioEventLoopGroup(); Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ChannelPipeline pipeline = ch.pipeline(); pipeline.addLast(new StringEncoder()); pipeline.addLast(new StringDecoder()); pipeline.addLast(new ClientHandler()); } }); ChannelFuture future = bootstrap.connect("localhost", 8888).sync(); future.channel().writeAndFlush("Hello, server!"); future.channel().closeFuture().sync(); group.shutdownGracefully(); ``` 在上面的示例中,我们创建了一个 Bootstrap 实例,并设置了客户端的 EventLoopGroup 和 Channel。然后使用 connect() 方法连接到服务端,并在连接成功后向服务端发送了一条消息。注意,在这里我们使用了 ChannelHandlerContext 的 writeAndFlush() 方法来发送数据。最后,我们等待连接关闭并关闭 EventLoopGroup。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值