当前位置: 首页 > 知识库问答 >
问题:

Netty-客户端/服务器聊天

冷浩瀚
2023-03-14

我需要在netty中有一个客户机/服务器通信,用于我的项目目的之一。所以我刚开始用一个handsOn来改进,我正在学习netty,我是一个初学者。

我尝试了一个简单的客户端服务器与Netty聊天。

客户端和服务器正在初始化,我可以看到服务器能够获得用于建立连接的客户端管道,但是当客户端发送消息时,它没有进入ServerAdapterHandler的messageReceived部分。下面是我的源代码,

客户:

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class ContainerClient {

    String server;
    int port;
    int containerPort;

    public ContainerClient(String server, int port, int containerPort) {
        this.server = server;
        this.port = port;
        this.containerPort = containerPort;
    }

    public static void main(String[] args) {
        String server = "localhost";
        int port = 5252;
        int containerPort = 8094;
        new ContainerClient(server, port, containerPort).start();
    }

    public void start() {
        EventLoopGroup group = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap().group(group)
                    .channel(NioSocketChannel.class)
                    .handler(new ClientAdapterInitializer());

            Channel channel = bootstrap.connect(server, port).sync().channel();

            channel.write("Hi\n");
            channel.write("Hi\n");
            channel.write("Hi\n");

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            group.shutdownGracefully();
        }
    }
}
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class ClientAdapterInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();

        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());

        pipeline.addLast("handler", new ClientAdapterHandler());
    }

}
 import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;

public class ClientAdapterHandler extends
        ChannelInboundMessageHandlerAdapter<String> {

    @Override
    public void messageReceived(ChannelHandlerContext context, String message)
            throws Exception {
        System.out.println(message);
        if (message.equals("quit"))
            throw new ServerEndedException("Server is closed");
    }

    @Override
    public void channelRead(ChannelHandlerContext arg0, Object arg1)
            throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void channelReadComplete(ChannelHandlerContext arg0)
            throws Exception {
        // TODO Auto-generated method stub

    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext arg0)
            throws Exception {
        // TODO Auto-generated method stub

    }

}
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class ContainerServer {

    int port;

    public static void main(String[] args) {
        new ContainerServer().start();
    }

    public void start() {
        port = 5252;
        EventLoopGroup producer = new NioEventLoopGroup();
        EventLoopGroup consumer = new NioEventLoopGroup();

        try {

            ServerBootstrap bootstrap = new ServerBootstrap()
                    .group(producer, consumer)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ServerAdapterInitializer());
            System.out.println("Server started");
            bootstrap.bind(port).sync().channel().closeFuture().sync();

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            producer.shutdownGracefully();
            consumer.shutdownGracefully();
        }

    }

}

服务器通道初始值设定项:

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class ServerAdapterInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();

        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());

        pipeline.addLast("handler", new ServerAdapterHandler());
    }

}

服务器消息处理程序

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundMessageHandlerAdapter;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.concurrent.GlobalEventExecutor;

public class ServerAdapterHandler extends
        ChannelInboundMessageHandlerAdapter<String> {

    private static final ChannelGroup channels = new DefaultChannelGroup(
            "containers", GlobalEventExecutor.INSTANCE);

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("[START] New Container has been initialzed");
        channels.add(ctx.channel());
        super.handlerAdded(ctx);
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        System.out.println("[END] A Container has been removed");
        channels.remove(ctx.channel());
        super.handlerRemoved(ctx);
    }

    @Override
    public void messageReceived(ChannelHandlerContext ctx, String arg1)
            throws Exception {
        Channel currentChannel = ctx.channel();
        System.out.println("[INFO] - " + currentChannel.remoteAddress() + " - "
                + arg1);
        currentChannel.write("[Server] - Success");

    }

    @Override
    public boolean beginMessageReceived(ChannelHandlerContext ctx)
            throws Exception {
        System.out.println("Message received");
        return super.beginMessageReceived(ctx);
    }

    @Override
    public void channelRead(ChannelHandlerContext arg0, Object arg1)
            throws Exception {
        System.out.println("channelRead");
    }

    @Override
    public void channelReadComplete(ChannelHandlerContext arg0)
            throws Exception {
        // TODO Auto-generated method stub
        System.out.println("channelReadComplete");
    }

    @Override
    public void channelWritabilityChanged(ChannelHandlerContext arg0)
            throws Exception {
        // TODO Auto-generated method stub
        System.out.println("channelWritabilityChanged");
    }

}

以下是我在服务器中获得的输出,而在客户端中没有任何输出:

Server started
[START] New Container has been initialzed
channelReadComplete
[END] A Container has been removed
Server started
[START] New Container has been initialzed
channelReadComplete
[INFO] - localhost - Hi
[INFO] - localhost - Hi
[INFO] - localhost - Hi
[END] A Container has been removed
[Server] - Success
[Server] - Success
[Server] - Success

共有1个答案

阎宾实
2023-03-14

通过对ContainerClient中的start方法进行以下更改,我可以使用它。只需添加channel.flush()

public void start() {
    EventLoopGroup group = new NioEventLoopGroup();

    try {
        Bootstrap bootstrap = new Bootstrap().group(group).channel(NioSocketChannel.class).handler(new ClientAdapterInitializer());

        Channel channel = bootstrap.connect(server, port).sync().channel();

        channel.write("Hi\n");
        channel.write("Hi\n");
        channel.write("Hi\n");
        channel.flush();

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        group.shutdownGracefully();
    }
}

ChannelInboundMessageHandlerAdapter在较新版本的4.0中不再存在。我使用了SimpleChannelInboundHandler

public class ServerAdapterHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        Channel currentChannel = ctx.channel();
        System.out.println("[INFO] - " + currentChannel.remoteAddress() + " - " + msg);
        currentChannel.write("[Server] - Success");
    }

}
 类似资料:
  • 似乎服务器拒绝了wireshark输出中的tls协商,但我从代码中看不出原因。它是基于工作的代码,只是它被否决了,因此我用新的API更新。代码是开始。需要使用真实的证书。有人知道为什么服务器发送tcp FIN,ack吗? 我有以下服务器代码: 23 16.856111 sonymobi_7f:55:af intelcor_25:1d:fc ARP 42 10.1.10.100在84:c7:ea:7

  • 在本节中,我们将构建一个完整的的 Netty客 户端和服务器。虽然你可能集中在写客户端是浏览器的基于 Web 的服务,接下来你将会获得更完整了解 Netty 的 API 是如何实现客户端和服务器的。 Figure 2.1.Echo client / server 图中显示了连接到服务器的多个并发的客户端。在理论上,客户端可以支持的连接数只受限于使用的 JDK 版本中的制约。 echo(回声)客户端

  • 在探索和实现Proact设计模式后,遇到了一个问题,即客户端(“C”客户端)连接在限制后不再接受。开始探索netty。这是我试图做的1。C客户端建立连接2。Java服务器接受连接并开始使用TCP向客户端发送8 Mb大小的字节缓冲区。有什么想法吗?netty是一个好的选择吗?我浏览了netty的一个很好的例子,不幸的是不走运。 先谢谢你。 尊敬的Ravi

  • 问题内容: 这实际上是我在这里的第一篇文章,一段时间以来我一直在试图弄清楚这一点,但是我终于打电话给该旗帜,并将尝试寻求有关此主题的一些帮助。 因此,我有一个客户端和一个服务器,它们是根据回显客户端/服务器和安全聊天客户端/服务器建模的。我对聊天的SSL部分和使用回显仅对确保我在客户端/服务器之间收到响应不感兴趣。我将在这篇文章的底部添加所有相关代码。我现在遇到的问题是,在客户端连接后,我可以从服

  • 我将创建一个身份验证服务器,它本身与一组不同的Oauth2.0服务器交互。Netty似乎是在这里实现网络部分的一个很好的候选者。但在开始之前,我需要澄清一些关于netty的细节,因为我是新手。例行程序如下: > < li> 服务器接受来自客户端的HTTPS连接。 然后,不关闭第一个连接,它通过HTTPS与远程OAuth2.0服务器建立另一个连接并获取数据 毕竟,服务器将结果发送回客户端,客户端应该

  • 这对我来说可能很明显,但我仍然想确认以下几点... 给定一个特定的通道和一个NIO Netty服务器,它使用OrderedMemoryAwareThreadPoolExecutor和以下形式的客户端: null 首先,请让我知道,如果以上是不正确的。如果有,请指正。 对于断言3),服务器仍然按照每个事件接收的顺序处理请求,但是由于客户机是异步的,所以发送请求的顺序是无法预测的。真的吗? 因此,从客