2012-06-11 39 views
0

我有一个关于ClientBootStrap的问题。 这是场景;Netty ClientBootstrap重新连接到另一台服务器

  1. Client_X想加入Server_A。
  2. 但Server_A以某种方式希望Client_x加入Server_B。
  3. 因此Server_A向Server_B发送Server_B的信息以进行重新连接
  4. 只要Client_X收到RECONNECTION消息,他就尝试断开与Server_A的连接并尝试连接到Server_B。 但它失败。因为一旦客户端从Server_A断开连接,他就不能再使用断开的通道。

这看起来很简单。但这里是我的执行

@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

是的,但NETTY自己创建通道。我们如何手动创建频道?我无法在API中看到。感谢您的建议艰难。 –

+0

就像你创建第一个socket一样:ChannelFuture f = b.connect()。sync(); – Veebs

+0

好的,我通过在创建时将引导对象传递给ChannelHandler来解决我的问题。所以只要通道处理程序断开连接,我就使用引导对象进行重新连接。谢谢Veebs。 –

相关问题