Java(Bukkit)Netty Client在第二个线程中启动时停止工作

时间:2018-04-06 21:59:36

标签: java netty bukkit

我在开发软件时遇到了问题。

我有一个Netty服务器和多个Netty客户端。但是,当我尝试在新线程中启动它们时,它们会在稍微调试消息后停止。客户端运行在Minecraft服务器软件Bukkit上。其他客户端的其他客户端运行在一个独立的Java程序上,它们工作得很好。

这是我的客户端类:

public class NettyClient extends Thread {

public boolean connected;


/**
 * Returns true if the client is connected.
 *
 * @return boolean
 */

String host;
int port;
public Channel channel;
public BlockingQueue<Packet> queue = new LinkedBlockingDeque<>();


public NettyClient(String host, int port) {
    this.host = host;
    this.port = port;
}


@Override
public void run() {
    boolean epoll = Epoll.isAvailable();
    System.out.println("[Sys] Server-Typ: " + (epoll ? "Epoll" : "Nio"));
    EventLoopGroup mainEventLoopGroup = epoll ? new EpollEventLoopGroup() : new NioEventLoopGroup();

    Bootstrap bootstrap = new Bootstrap();


    try {
        bootstrap.group(mainEventLoopGroup)
                .channel(epoll ? EpollSocketChannel.class : NioSocketChannel.class)
                .handler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(final SocketChannel socketChannel) throws Exception {
                        socketChannel.pipeline().addLast("encoder", new PacketEncoder());
                        socketChannel.pipeline().addLast("decoder", new PacketDecoder());
                        socketChannel.pipeline().addLast("wrapperhandler", new WrapperHandler());
                    }
                });
        ChannelFuture f = bootstrap.connect(host, port).channel().closeFuture().syncUninterruptibly();
        this.channel = f.channel();
        System.out.println("Succesfully established connection to the wrapper server!");
       channel.writeAndFlush(new PacketServerLogIn(System.getProperty("servername"),System.getProperty("servergroup"), Bukkit.getServer().getIp(),Bukkit.getOnlinePlayers().size(),Bukkit.getMaxPlayers(),ServerState.WAITING));
      RedisBuilder.getInstance().startUpdateScheduler();


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

    }
}




public String getHost() {
    return host;
}

public int getPort() {
    return port;
}

public Channel getChannel() {
    return channel;
}
public boolean isConnected() {
    return connected;
}

}

这是我的服务器:

公共类NetworkServer {

String host;
int port;

public NetworkServer(String host, int port) {
    this.host = host;
    this.port = port;
}


public void run() {
    boolean epoll = Epoll.isAvailable();
    System.out.println("[Sys] Server-Typ: " + (epoll ? "Epoll" : "Nio"));
    EventLoopGroup mainEventLoopGroup = epoll ? new EpollEventLoopGroup(2) : new NioEventLoopGroup(2);
    EventLoopGroup workerEventLoopGroup = epoll ? new EpollEventLoopGroup(2) : new NioEventLoopGroup(2);
    ServerBootstrap serverBootstrap = new ServerBootstrap();

    try {
        serverBootstrap.group(mainEventLoopGroup, workerEventLoopGroup)
                .channel(epoll ? EpollServerSocketChannel.class : NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(final SocketChannel socketChannel) throws Exception {
                        final SSLContext sslContext = SSLFactory.createAndInitSSLContext("client.jks");
                        final SSLEngine sslEngine = sslContext.createSSLEngine();
                        sslEngine.setUseClientMode(false);
                        sslEngine.setEnabledCipherSuites(sslContext.getSocketFactory().getSupportedCipherSuites());

                        socketChannel.pipeline().addLast("ssl", new SslHandler(sslEngine));
                        //  socketChannel.pipeline().addLast(ZlibCodecFactory.newZlibEncoder(ZlibWrapper.GZIP));
                        //socketChannel.pipeline().addLast(ZlibCodecFactory.newZlibDecoder(ZlibWrapper.GZIP));
                        socketChannel.pipeline().addLast("decoder", new PacketDecoder());
                        socketChannel.pipeline().addLast("encoder", new PacketEncoder());
                        socketChannel.pipeline().addLast("wrapperhandler", new WrapperHandler());
                    }
                });
        serverBootstrap.bind(port).channel().closeFuture().sync();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        mainEventLoopGroup.shutdownGracefully();
        workerEventLoopGroup.shutdownGracefully();
    }
}


public String getHost() {
    return host;
}

public int getPort() {
    return port;
}

}

我认为Bukkit不喜欢多线程,但如果我错了,请纠正我。

My Netty版本是:4.1.2.Final

2 个答案:

答案 0 :(得分:0)

您的问题是由于您正在调用.shutdownGracefully();引起的,这基本上是对Netty线程&amp;他们应该关闭的渠道。

由于您正在开发BUkkit插件,因此您应该只在插件的onDisable()部分内调用这些方法。

答案 1 :(得分:0)

对于所有也遇到此错误的人:我找到了解决方法。

您需要使用maven来编译正确的Netty版本。

 <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
                <shadedArtifactAttached>true</shadedArtifactAttached>
                <relocations>
                    <relocation>
                        <pattern>io.netty</pattern>
                        <shadedPattern>io.nettynew</shadedPattern>
                    </relocation>
                </relocations>
            </configuration>
            <executions>

                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>

这会将正确的netty版本重新着色到最终的jar中,现在您可以连接到另一台netty服务器,而不会出现任何问题。确保已将Netty依赖项添加到maven:

<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.29.Final</version>