【问题标题】:How to write messages using netty client?如何使用 netty 客户端编写消息?
【发布时间】:2018-07-10 09:02:18
【问题描述】:

我正在尝试使用 Netty 构建一个简单的 TCP 客户端-服务器应用程序。 一开始我是这样通过SocketChannel从客户端发送消息的:

    SocketChannel client = SocketChannel.open(hostAddress);
    client.write(buffer);

所有消息都由服务器接收,但是当我想将响应写回客户端时,我看到为了获得客户端的响应,它需要通过引导程序发送消息并定义 Inboundhandler会阅读回复(也许有人知道另一种方式?) 当我尝试通过引导程序发送消息时,我使用以下代码:

    EventLoopGroup group = new NioEventLoopGroup();
    Bootstrap b = new Bootstrap();
    b.group(group).channel(NioSocketChannel.class);
    b.handler(new ChannelInitializer<SocketChannel>() {

        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            // TODO Auto-generated method stub
            ch.pipeline().addLast(new TestClientHandler());
        }

      });
    ChannelFuture future = bootstrap.connect(hostAddress);
    future.channel().writeAndFlush(buffer);

但是这样服务器根本就没有收到消息! 这是我用于服务器的代码(当我不通过客户端的引导程序发送消息时工作正常):

    bootstrap = new ServerBootstrap();
    bootstrap.group(boosGroup, workerGroup);
    bootstrap.channel(NioServerSocketChannel.class);
    bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
            @Override
            protected void initChannel(SocketChannel ch) throws Exception {
              ChannelPipeline pipeline = ch.pipeline();
              pipeline.addLast(dnsMessageDecodingHandler); 
              pipeline.addLast(group,"DnsTcpHandler",dnsTcpHandler); 
            }
          });
     future = bootstrap.bind(hostAddress).await();

在 Netty 中编写简单的客户端-服务器的正确方法是什么?我没有找到任何可行的例子......

谢谢, 奥斯纳特。

【问题讨论】:

  • 缺少 ServerBootstrap.bind() 调用?
  • 有的,只是我没有复制
  • 现在我也在客户端添加了绑定,但没有帮助
  • 向服务器通道处理程序添加一个 LoggingHandler 并查看它是否调用了 bind()。如果绑定成功,请检查您的客户端是否可以访问您的地址
  • 客户端和服务器都在我的电脑上运行在不同的端口...

标签: java netty


【解决方案1】:

你应该知道 TCP 连接是如何工作的

本文描述了典型的 TCP 流。 https://www.ibm.com/support/knowledgecenter/en/SSB23S_1.1.0.14/gtps7/s5tcpcf.html

看完文章你需要正确编写服务器代码

// create your server bootstrap
ServerBootstrap b = new ServerBootstrap();

// add your ChannelInitializer which handles when client has been connected to your server
// in ChannelInitializer you need to register your ChannelHandler, such as ChannelDuplexHandler to client channel pipeline
b.childHandler(YOUR_CHANNEL_INITIALIZER); 

b.bind(bindAddress); // your server will now listen() for client connect()

运行引导代码后,客户端可以连接到服务器

【讨论】:

  • 你的处理程序和绑定调用在哪里
  • 我已添加:b.bind(bindAddress).sync();但这没有帮助。
【解决方案2】:

netty 仓库中有多个示例,我不知道你为什么说没有。

https://github.com/netty/netty/tree/4.1/example

也就是说,我怀疑问题在于您没有“等待”直到 connect(...) 操作完成。如果您检查 writeAndFlush(...) 返回的 ChannelFuture 结果,它会告诉您这一点。

S所以快速解决方法是:

ChannelFuture future = bootstrap.connect(hostAddress).await();
future.channel().writeAndFlush(buffer);

【讨论】:

  • 1.我已经在connect中添加了await(0方法,但是服务器仍然没有收到消息。
  • 2.返回结果Future原因是:java.lang.UnsupportedOperationException:不支持的消息类型:HeapByteBuffer(预期:ByteBuf,FileRegion)。你知道这是什么意思吗?
  • 异常告诉你什么...你只能写ByteBuf或FileRegion,但你写了ByteBuffer。
【解决方案3】:

在我检查了从 writeAndFlush 返回的 ChannelFuture 的原因之后(就像 Norman Maurer 建议我的那样),我看到原因是:不支持的消息类型:HeapByteBuffer(预期:ByteBuf,FileRegion) 这是因为我没有将 ObjectEncoder 添加到客户端管道! 这个添加解决了这个问题: b.handler(new ChannelInitializer() {

        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            // TODO Auto-generated method stub
            ch.pipeline().addLast(new ObjectEncoder());
            ch.pipeline().addLast(new TestClientHandler());
        }

      });

感谢所有帮助过我的人! 奥斯纳特。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-01-16
    • 1970-01-01
    • 2012-12-05
    • 2015-04-07
    • 2012-06-21
    • 2021-06-07
    • 1970-01-01
    • 2017-10-26
    相关资源
    最近更新 更多