Netty入门-客户端与服务端双向通信

26 篇文章 1 订阅
13 篇文章 0 订阅
  • 服务端启动并指定连接数据读写逻辑

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

public class NettyServer {
    public static void main(String[] args) {
        EventLoopGroup bossGroup=new NioEventLoopGroup();
        EventLoopGroup workerGroup=new NioEventLoopGroup();

        ChannelFuture channelFuture = new ServerBootstrap()
                .group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        // 指定连接数据读写逻辑
                        ch.pipeline().addLast(new MyServerHandler());
                    }
                }).bind(9999);

        channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (future.isSuccess()) {
                    System.out.println("端口绑定成功!");
                } else {
                    System.err.println("端口绑定失败!");
                }
            }
        });
    }
}
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.nio.charset.Charset;

public class MyServerHandler extends ChannelInboundHandlerAdapter {

    //收到数据之后调用
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println("服务端读到数据:" + byteBuf.toString(Charset.forName("utf-8")));

        System.out.println("服务端写出数据");
        ByteBuf buffer=ctx.alloc().buffer();
        buffer.writeBytes("ready".getBytes(Charset.forName("utf-8")));
        ctx.writeAndFlush(buffer);
    }
}

  • 客户端连接并指定连接数据读写逻辑

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;

import java.net.InetSocketAddress;

public class NettyClient {
    public static void main(String[] args) {
        EventLoopGroup client = new NioEventLoopGroup();

        ChannelFuture channelFuture = new Bootstrap()
                .group(client)
                .channel(NioSocketChannel.class)
                .handler(new ChannelInitializer<NioSocketChannel>() {
                    @Override
                    protected void initChannel(NioSocketChannel ch) throws Exception {
                        ChannelPipeline pipeline = ch.pipeline();
                        // 指定连接数据读写逻辑
                        pipeline.addLast(new MyClientHandler());
                    }
                })
                .connect(new InetSocketAddress("127.0.0.1", 9999));

        channelFuture.addListener(new GenericFutureListener<Future<? super Void>>() {
            @Override
            public void operationComplete(Future<? super Void> future) throws Exception {
                if (future.isSuccess()) {
                    System.out.println("连接成功");
                } else {
                    System.out.println("连接失败");
                }
            }
        });
    }
}
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.nio.charset.Charset;

/**
 * 向服务端写数据的处理器
 */
public class MyClientHandler extends ChannelInboundHandlerAdapter {
    //在客户端连接建立成功之后被调用
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        System.out.println("服务端写出数据");
        // 1. 准备数据
        // 1.1 获取二进制抽象 ByteBuf
        ByteBuf buffer = ctx.alloc().buffer();
        // 1.2 指定字符串的字符集为 utf-8
        byte[] bytes = "hello server!".getBytes(Charset.forName("utf-8"));
        // 1.3 填充数据到 ByteBuf
        buffer.writeBytes(bytes);

        // 2. 写数据并发送
        ctx.channel().writeAndFlush(buffer);
    }
    //收到数据之后调用
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf= (ByteBuf) msg;
        System.out.println("客户端读到数据:"+byteBuf.toString(Charset.forName("utf-8")));
        //给连接设置属性,如登录成功标识等
        //ctx.channel().attr(CLIENT_FLAG).set(true);
    }
}
  1. 客户端和服务端的逻辑处理均是在启动的时候(childHandler或handler方法中),通过给逻辑处理链 pipeline 添加逻辑处理器,来编写数据的读写逻辑
  2. 在客户端连接成功之后会回调到逻辑处理器的 channelActive() 方法,而不管是服务端还是客户端,收到数据之后都会调用到 channelRead 方法
  3. 写数据调用ctx.channel().writeAndFlush()方法,客户端与服务端交互的二进制数据载体为 ByteBufByteBuf 通过连接的内存管理器创建,字节数据填充到 ByteBuf 之后才能写到对端(buffer.writeBytes(bytes))
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值