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

时间:2012-06-11 23:26:10

标签: netty

我对ClientBootStrap有疑问。 这是场景;

  1. Client_X想要加入Server_A。
  2. 但Server_A不知何故希望Client_x加入Server_B。
  3. 因此Server_A将Server_B的信息发送到Client_X以进行RECONNECTION
  4. 一旦Client_X收到RECONNECTION消息,他就会尝试断开与Server_A的连接并尝试连接到Server_B。 但它失败了。因为一旦客户端断开与Server_A的连接,他就不能再使用断开连接的通道了。
  5. 这看起来很简单。但这是我的实施

        @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);
    
    }
    

    但我需要了解Client_X的一些信息。一旦Client_x断开连接,管道就会创建另一个SimpleChannelHandler。所以我的所有信息都消失了。我尝试使用ChannelLocal来保持客户端的状态。但它也没用,因为它与通道对象有关。当我连接到newChannel时,我再也无法使用旧的SimpleChannelHandlers数据。 (如clientID,roomID等)

    我的观点是如何在不受通道(会话)影响的情况下存储信息,我想从任何通道处理程序访问数据。

    处理这个问题的方法是我们应该像这样实现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 个答案:

答案 0 :(得分:1)

尝试创建新频道,而不是尝试重新打开已关闭的频道。

您可能希望实施回调以启动新频道的制作。