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

Netty ClientBootstrap重新连接到另一台服务器

邵捷
2023-03-14

我有一个关于ClientBootstrap的问题。下面是场景;

    null
    @Override
public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)throws Exception  {
    if(e.getMessage() instanceof SomePacket){
    ....
    }else if(e.getMessage() instanceof Reconnect){ //Server_A has sent a RECONNECT Message.(Redirection)
        Reconnect theReconnectPacket = (Reconnect)e.getMessage();
        String hostname = theReconnectPacket.getHostname();
        int port = theReconnectPacket.getPort();

        this.reconnectHost  = hostname;
    this.reconnectPort  = port;
    this.currentState   = 1;

    ctx.getChannel().disconnect();    //DISCONNECT FROM SERVER_A

     }
}

@Override
public void channelDisconnected(ChannelHandlerContext ctx,ChannelStateEvent e) throws Exception {

     if(this.currentState == 1){

        Channel disconnectedChannel = ctx.getChannel();

    if (!disconnectedChannel.isConnected()){

    SocketAddress destinationAddress = new InetSocketAddress(this.reconnectHost, this.reconnectPort);
           //TRYING TO RECONNECT SERVER_B
    disconnectedChannel.connect(destinationAddress);    //**Error Line:java.nio.channels.ClosedChannelException**

    }

      }


    super.channelDisconnected(ctx, e);
}

正如您在错误行中看到的,我得到了这个异常:java.nio.channels.ClosedChannelException。我们不能在断开后使用相同的频道吗?。一旦断开,就完成了吗?。我们如何在SimpleChannelHandler中重新创建连接?

感谢进一步的评论:)

<<<<<<新方法>>>>>

在SimpleChannledHandler中,我使用ClientBootStrap连接一个不同的端口。

 @Override
public void channelDisconnected(ChannelHandlerContext ctx,ChannelStateEvent e) throws Exception {

       Channel disconnectedChannel = ctx.getChannel();
    final ClientDataObject oldObject = ClientDataState.clientObject.get(disconnectedChannel);

    if(oldObject.getClientState() == 1){

        if (!disconnectedChannel.isConnected()){

SocketAddress destinationAddress = new InetSocketAddress(this.reconnectHost, this.reconnectPort);

ChannelFuture connectFuture = bootstrap.connect(destinationAddress);

connectFuture.addListener(new ChannelFutureListener() {
    @Override
    public void operationComplete(ChannelFuture channelFuture) throws Exception {

        Channel newChannel = channelFuture.getChannel();
    ClientDataObject newObject =  ClientDataState.clientObject.get(newChannel);
                      newObject.setClientID(oldObject.getClientID());


                     newObject.setClientState(oldObject.getClientState());
                    newObject.setRoomId(oldObject.getRoomId());
                    newObject.setClientState(1);

                    ClientDataState.clientObject.set(newChannel, newObject);

                    Channels.write(newChannel, new Login(newObject.getClientID()));
               }});             

        }else{
                     //Channled connected
            }

    }

    super.channelDisconnected(ctx, e);

}

处理这个问题的方法我们应该这样实现ChannelPipelineFactory吗?

   public class GameClientPipelineFactory implements ChannelPipelineFactory{

      private static final ClientStaticHandler SHARED = new ClientStaticHandler();  

           private Someobject o;
public GameClientPipelineFactory(Someobject refTOSomeObject) {
    super();
    this.o = refToSomeObject;
}

@Override
public ChannelPipeline getPipeline() throws Exception {
    // TODO Auto-generated method stub
    ChannelPipeline pipeline = Channels.pipeline();

    //pipeline.addLast("delimiter", new DelimiterBasedFrameDecoder(256, Delimiters.lineDelimiter()));
    pipeline.addLast("decoder", new GameClientDecoder());
    pipeline.addLast("encoder", new GameClientEncoder());
    pipeline.addLast("shared", SHARED); //I added this line

    pipeline.addLast("logicHandler", new GameClientLogicHandler(this.o));

    return pipeline;

}

但我该如何使用这个“共享”处理程序呢?每次当我需要一个全局对象时,我是否应该请求管道来获得这个处理程序,并从“共享”处理程序中获得任何对象?这不是很远吗?

共有1个答案

朱炳
2023-03-14

与其尝试重新打开已关闭的通道,不如尝试创建一个新通道。

您可能希望实现一个回调来启动新通道的创建。

 类似资料:
  • 问题内容: 是否有TSQL命令连接到另一台服务器? 或在查询窗口中时,用于连接到另一台服务器并显示查询窗口的快捷键是什么? 我在某些屏幕上已经看到Ctrl + N弹出“ 连接到服务器” 对话框,但是当我已经在查询窗口中并按Ctrl + N时,它将打开另一个查询窗口。 USE命令可让您连接到当前服务器上的其他数据库,但是是否有命令可让您连接到另一台服务器? 我正在使用SQL Server 2005。

  • 问题内容: 我可以在服务器A上安装php脚本并连接到服务器B上的MySQL数据库吗? 如果是,将如何进行?提前致谢 问题答案: 其简单的上述所有方法都非常复杂 假设您在服务器B上有数据库,在服务器A上有网站(假设它的IP为192.234.12.1) 在cpanel上将服务器B的IP列入白名单 并在数据库中创建一个具有足够特权的新用户(例如,该用户已经过测试) 然后将该用户创建为test@192.2

  • 我无法将一台unix服务器的安全服务器连接到另一台unix服务器。从putty到ssh,我能够轻松连接,但当从jsch连接时,我发现错误如下。 成功的腻子步骤- jsch步骤-- 连接会话 错误:-将不分配伪终端,因为stdin不是终端。权限被拒绝,请重试。权限被拒绝,请重试。权限被拒绝(公钥、密码、键盘交互)。ksh:changeme:未找到退出状态:127 jsch示例程序- JAVAutil

  • 问题内容: 我需要将Jenkins 2.32版从服务器A移至Jenkins 2.72.1服务器B。两台服务器均具有ubuntu 16.04.3,由于内存问题,我无法安装任何插件,也无法在服务器A中使用该插件。有什么办法可以实现这一目标? 问题答案: 将目录中的所有文件复制到新服务器。 将新服务器指向新目录。 将Jenkins war文件(或servlet容器设置,如果有的话)复制到新机器上并启动它

  • 我使用的代码女巫只允许4个不同端口上的4个连接。此代码正在工作,但当客户端关闭连接时,它无法重新建立连接。连接被拒绝。认为是因为线程关闭。如何解决这个问题?我无法更改端口号... 从套接字导入* BUFF=25 def服务器(主机、端口): 如果名称==“main”:导入线程

  • 问题内容: 我目前有一个在云实例上运行的实时Redis服务器,我想将此Redis服务器迁移到新的云实例并将该实例用作我的新Redis服务器。如果是MySQL,我将从旧服务器中导出数据库并将其导入新服务器中。我应该如何使用redis? PS:我不想设置复制。我想将Redis服务器完全迁移到新实例。 问题答案: 通过运行或从命令行将数据库快照保存到dump.rdb中。这将在与Redis服务器相同的文件