Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/374.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Netty object echo示例服务器channelRead方法不适用于我的自定义对象_Java_Object_Echo_Netty_Pojo - Fatal编程技术网

Java Netty object echo示例服务器channelRead方法不适用于我的自定义对象

Java Netty object echo示例服务器channelRead方法不适用于我的自定义对象,java,object,echo,netty,pojo,Java,Object,Echo,Netty,Pojo,我最近开始尝试使用Netty来创建视频游戏服务器/客户端关系。我正在使用Netty 4.1.X源提供的Netty“Object Echo”示例。客户机和服务器包含在单独的项目中。“VersionInfo”类在服务器和客户端项目中都可用,但具有不同的包名称 我遇到的问题是,当我将自定义对象从客户端发送到服务器时,它没有被接收。然而,如果我发送一个字符串对象,它就可以完美地工作 服务器: public class Server { private int port; pub

我最近开始尝试使用Netty来创建视频游戏服务器/客户端关系。我正在使用Netty 4.1.X源提供的Netty“Object Echo”示例。客户机和服务器包含在单独的项目中。“VersionInfo”类在服务器和客户端项目中都可用,但具有不同的包名称

我遇到的问题是,当我将自定义对象从客户端发送到服务器时,它没有被接收。然而,如果我发送一个字符串对象,它就可以完美地工作

服务器:

    public class Server {
    private int port;

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

    public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();

            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ServerChannelInitializer())
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);

            // Bind and start to accept incoming connections.
            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();

            // Wait until the server socket is closed.
            // In this example, this does not happen, but you can do that to gracefully
            // shut down your server.
            channelFuture.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        try {
            new Server(1337).run();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
服务器通道初始值设定项:

    public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    public void initChannel(SocketChannel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();

        pipeline.addLast(new ObjectEncoder());
        pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
        pipeline.addLast(new ObjectEchoServerHandler());
    }
}
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    public void initChannel(SocketChannel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();

        pipeline.addLast(new ObjectEncoder());
        pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
        pipeline.addLast(new ObjectEchoClientHandler());
    }
}
VersionInfo类(在客户端和服务器上,但包名不同):

现在转到客户机代码:

public class Client {
    public static void main(String[] args) throws Exception {

        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(workerGroup);
            bootstrap.channel(NioSocketChannel.class);
            bootstrap.option(ChannelOption.TCP_NODELAY, true);
            bootstrap.option(ChannelOption.SO_KEEPALIVE, true);
            bootstrap.handler(new ClientChannelInitializer());

            // Start the client.
            ChannelFuture channelFuture = bootstrap.connect("localhost", 1337).sync(); // (5)

            // Wait until the connection is closed.
            channelFuture.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
        }
    }
}
ClientChannelInitializer:

    public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> {

    public void initChannel(SocketChannel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();

        pipeline.addLast(new ObjectEncoder());
        pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
        pipeline.addLast(new ObjectEchoServerHandler());
    }
}
public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    public void initChannel(SocketChannel channel) throws Exception {
        ChannelPipeline pipeline = channel.pipeline();

        pipeline.addLast(new ObjectEncoder());
        pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
        pipeline.addLast(new ObjectEchoClientHandler());
    }
}
在ObjectEchoClientHandler channelActive方法中发送字符串可以正常工作。发送自定义POJO/对象不会调用ObjectEchoServerHandler channelRead方法

这可能是什么原因造成的

编辑#1:根据Nicholas的建议在下面添加日志文本。很抱歉在日志调试过程中出现了blockquote。堆栈溢出编辑器不允许我在没有它的情况下提交它

VersionInfo类已更改,以反映相同的包名称。新类别:

package com.nettytest.iocommon;

public class VersionInfo {
    public String version = "1.0.0";
    public boolean versionChecked = false;
}
发送自定义Pojo后的客户端输出

2017年3月22日下午1:09:43 io.netty.handler.logging.LoggingHandler 信道注册严重:[id:0x237af0b8]于2017年3月22日注册 下午1:09:43 io.netty.handler.logging.LoggingHandler连接严重: [id:0x237af0b8]连接:本地主机/127.0.0.1:1337[客户端]正在发送 版本信息2017年3月22日下午1:09:43 io.netty.handler.logging.LoggingHandler通道活动严重:[id: 0x237af0b8,L:/127.0.0.1:52830-R:localhost/127.0.0.1:1337]处于活动状态
2017年3月22日下午1:09:43 io.netty.handler.logging.LoggingHandler写入 严重:[id:0x237af0b8,L:/127.0.0.1:52830- R:localhost/127.0.0.1:1337]写入: com.nettytest.iocommon。VersionInfo@7544bac2017年3月22日下午1:09:43 io.netty.handler.logging.LoggingHandler刷新严重:[id: 0x237af0b8,L:/127.0.0.1:52830-R:localhost/127.0.0.1:1337]刷新

接收自定义Pojo后的服务器输出

2017年3月22日下午1:09:43 io.netty.handler.logging.LoggingHandler channelRegistered[服务器]通道活动严重:[id:0xcdffaece, L:/127.0.0.1:1337-R:/127.0.0.1:52830]于2017年3月22日注册 下午1:09:43 io.netty.handler.logging.LoggingHandler通道活动
严重:[id:0xCDF,L:/127.0.0.1:1337-R:/127.0.0.1:52830] 活跃的


调试的一种方法是向服务器管道中添加一个。大概是这样的:

import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.logging.LogLevel;
....
final LoggingHandler loggingHandler = new LoggingHandler(getClass(), 
LogLevel.ERROR);
....
pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
pipeline.addLast("logger", loggingHandler);
pipeline.addLast(new ObjectEchoServerHandler());
....

我最初的怀疑是,由于您传递的pojo类型在客户端和服务器上具有不同的包名(这意味着它们不是同一个类),因此客户端上的ObjectDecoder失败,因为它无法在其类路径中找到该类。要使其正常工作,该类必须存在于服务器和客户端类路径中。

我已按照您的建议添加了记录器,并使VersionInfo类的包名与两个项目完全相同。我已经用记录器的详细信息更新了问题。不幸的是,堆栈溢出编辑器认为调试信息是未格式化的代码。因为只有相同的包名仍然不起作用,所以我更进一步。我将VersionInfo类放在一个单独的项目中。然后,我将该项目编译为jar文件。然后,我将该jar文件作为外部库添加到客户机和服务器项目中。将JAR添加到项目类路径中。这两个项目都认可这个类,但它仍然不起作用。而且记录器的输出信息不是很丰富,很奇怪。我将尝试从您提供的代码中复制。我不是测试的目标,但是VersionInfo类是否需要实现可序列化?字符串does和so does List(列表在正式的ObjectEcho示例中使用)。这可能就是问题所在。如果我没记错的话,您需要实现serializeable来手工编写网络代码。同时,感谢您迄今为止的所有帮助!正如我在前面的评论中提到的,我需要实现序列化。这样做修复了问题,项目现在按预期运行。谢谢你的帮助!
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.logging.LogLevel;
....
final LoggingHandler loggingHandler = new LoggingHandler(getClass(), 
LogLevel.ERROR);
....
pipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
pipeline.addLast("logger", loggingHandler);
pipeline.addLast(new ObjectEchoServerHandler());
....