使用netty编写客户端,实现同步发送消息并接收返回结果

1 篇文章 0 订阅

使用netty编写客户端,实现同步发送消息并接收返回结果

描述

在网上找了很久都没有找到自己想要的代码,今天就自己研究了一下,使用了CountDownLatch实现了发送之后可以接收返回结果。

服务端

MyServerNetty

package com.chen.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.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;

public class MyServerNetty {
    private int port;

    public MyServerNetty(int port) {
        this.port = port;
    }

    public void action(){
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        NioEventLoopGroup workerGroup = new NioEventLoopGroup();

        try{
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            ((ServerBootstrap)((ServerBootstrap)((ServerBootstrap)serverBootstrap.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)).option(ChannelOption.SO_BACKLOG, 128)).childOption(ChannelOption.SO_KEEPALIVE, true).handler(new LoggingHandler(LogLevel.INFO))).childHandler(new ChannelInitializer<SocketChannel>() {
                protected void initChannel(SocketChannel socketChannel) throws Exception {
                    socketChannel.pipeline().addLast(new ChannelHandler[]{new MyServerHandler()});
                }
            });
            System.err.println("server 开启--------------");
            ChannelFuture cf = serverBootstrap.bind(this.port).sync();
            cf.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        (new MyServerNetty(9999)).action();
        System.out.println("main==============>启动服务端");
    }
}

MyServerHandler

package com.chen.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

public class MyServerHandler extends ChannelInboundHandlerAdapter {

    public MyServerHandler() {
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf byteBuf = (ByteBuf) msg;
        byte[] bytes = new byte[byteBuf.readableBytes()];
        byteBuf.readBytes(bytes);
        String msg_str = new String(bytes,"UTF-8");
        System.out.println("===========>接收客户端消息:"+msg_str);
        System.out.println("===========>向客户端发送消息:"+msg_str);
        ctx.writeAndFlush(Unpooled.copiedBuffer(msg_str.getBytes()));
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.err.println("服务端读取数据完毕");
    }

}

客户端

MyNettyClient

package com.chen.netty;

import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.io.UnsupportedEncodingException;
import java.util.concurrent.CountDownLatch;

public class MyClientNetty {
    public static CountDownLatch countDownLatch = new CountDownLatch(1);
    public static CountDownLatch countDownLatch2 = new CountDownLatch(1);
    private String ip;
    private int port;
    private static ChannelFuture cf;
    private static EventLoopGroup bossGroup;

    public MyClientNetty(String ip, int port) {
        this.ip = ip;
        this.port = port;
    }

    public String sendRecv(String msg){
        try {
            cf.channel().writeAndFlush(Unpooled.copiedBuffer(msg.getBytes()));
            MyClientNetty.countDownLatch.await();
            return MyClientHandler.message;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public void connect() throws UnsupportedEncodingException, InterruptedException {
        this.action();
        countDownLatch2.await();
    }

    public void close() throws InterruptedException {
        cf.channel().closeFuture().sync();
        bossGroup.shutdownGracefully();
    }

    public void action() throws InterruptedException, UnsupportedEncodingException {
        bossGroup = new NioEventLoopGroup();
        final Bootstrap bs = new Bootstrap();

        ((Bootstrap)((Bootstrap)((Bootstrap)((Bootstrap)bs.group(bossGroup)).channel(NioSocketChannel.class)).option(ChannelOption.SO_KEEPALIVE, true)).option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(65535))).handler(new ChannelInitializer<SocketChannel>() {
            protected void initChannel(SocketChannel socketChannel) throws Exception {
                socketChannel.pipeline().addLast(new ChannelHandler[]{new MyClientHandler()});
            }
        });

        (new Thread(new Runnable() {
            public void run() {
                try {
                    MyClientNetty.cf = bs.connect(MyClientNetty.this.ip, MyClientNetty.this.port).sync();
                    MyClientNetty.countDownLatch2.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
        })).start();
    }

    public static void main(String[] args) {

        try {
            MyClientNetty myClientNetty = new MyClientNetty("127.0.0.1",9999);
            myClientNetty.connect();
            String result = myClientNetty.sendRecv("hello world");
            System.out.println(result);
            myClientNetty.close();
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}

MyNettyHandler

package com.chen.netty;

import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.ReferenceCountUtil;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;

public class MyClientHandler extends ChannelInboundHandlerAdapter {
    public static String message;

    public MyClientHandler() {
    }

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        try {
            ByteBuf byteBuf = (ByteBuf)msg;
            byte[] bytes = new byte[byteBuf.readableBytes()];
            byteBuf.readBytes(bytes);
            message = new String(bytes);
            MyClientNetty.countDownLatch.countDown();
        } finally {
            ReferenceCountUtil.release(msg);
        }

    }

    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
        System.err.println("客户端读取数据完毕");
        ctx.close();
    }

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.err.println("client 读取数据出现异常");
        ctx.close();
    }
}

总结

代码直接复制,运行,然后自己跟踪一下。

  • 7
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 12
    评论
好的,下面是一个简单的 Netty 客户端和服务端示例代码,可以相互发送消息: 服务端代码: ```java public class NettyServerHandler extends ChannelInboundHandlerAdapter { @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // 接收客户端消息 ByteBuf buf = (ByteBuf) msg; String request = buf.toString(CharsetUtil.UTF_8); System.out.println("Client request: " + request); // 向客户端发送响应消息 String response = "Hello, Client!"; ByteBuf respBuf = Unpooled.copiedBuffer(response, CharsetUtil.UTF_8); ctx.writeAndFlush(respBuf); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // 发生异常时关闭连接 cause.printStackTrace(); ctx.close(); } } ``` 客户端代码: ```java public class NettyClientHandler extends ChannelOutboundHandlerAdapter { private ChannelHandlerContext ctx; @Override public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { // 向服务器发送消息 ByteBuf buf = Unpooled.copiedBuffer(msg.toString(), CharsetUtil.UTF_8); ctx.writeAndFlush(buf); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { this.ctx = ctx; } @Override public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { // 接收服务端的响应 ByteBuf buf = (ByteBuf) msg; String response = buf.toString(CharsetUtil.UTF_8); System.out.println("Server response: " + response); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { // 发生异常时关闭连接 cause.printStackTrace(); ctx.close(); } } ``` 启动代码: ```java public class NettyDemo { public static void main(String[] args) throws InterruptedException { // 创建 EventLoopGroup EventLoopGroup group = new NioEventLoopGroup(); try { // 创建 ServerBootstrap ServerBootstrap serverBootstrap = new ServerBootstrap(); // 配置 ServerBootstrap serverBootstrap.group(group) .channel(NioServerSocketChannel.class) .localAddress(new InetSocketAddress(8888)) .childHandler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new NettyServerHandler()); } }); // 启动服务端 ChannelFuture serverFuture = serverBootstrap.bind().sync(); // 创建 Bootstrap Bootstrap clientBootstrap = new Bootstrap(); // 配置 Bootstrap clientBootstrap.group(group) .channel(NioSocketChannel.class) .remoteAddress(new InetSocketAddress("localhost", 8888)) .handler(new ChannelInitializer<SocketChannel>() { @Override protected void initChannel(SocketChannel ch) throws Exception { ch.pipeline().addLast(new NettyClientHandler()); } }); // 启动客户端 ChannelFuture clientFuture = clientBootstrap.connect().sync(); // 客户端向服务器发送消息 NettyClientHandler clientHandler = (NettyClientHandler) clientFuture.channel().pipeline().last(); clientHandler.write("Hello, Server!"); // 关闭客户端和服务端 clientFuture.channel().closeFuture().sync(); serverFuture.channel().closeFuture().sync(); } finally { // 释放资源 group.shutdownGracefully().sync(); } } } ``` 在上面的代码中,服务端使用 `ChannelInboundHandlerAdapter` 处理客户端的请求,客户端使用 `ChannelOutboundHandlerAdapter` 向服务端发送请求。在启动代码中,先启动服务端,再启动客户端,并使用 `ChannelFuture` 对象获取客户端的 `NettyClientHandler` 对象,通过该对象向服务端发送消息。需要注意的是,客户端和服务端都需要使用同一个 `EventLoopGroup`。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值