【问题标题】:Netty ClientBootstrap RECONNECT to another serverNetty ClientBootstrap RECONNECT 到另一台服务器
【发布时间】:2012-06-11 23:26:10
【问题描述】:

我有一个关于 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 断开,他就不能再使用断开的通道。

这看起来很简单。但这是我的实现

    @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 中重新创建连接?

感谢更多的 cmets :)

>>>>>

好的。所以在 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;

}

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

【问题讨论】:

    标签: netty


    【解决方案1】:

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

    您可能希望实现回调以启动新频道的创建。

    【讨论】:

    • 是的,但是 NETTY 自己创建频道。我们如何手动创建频道?我在 API 中看不到。谢谢你的忠告。
    • 就像你创建第一个套接字一样:ChannelFuture f = b.connect().sync();
    • 好的,我通过在创建时将引导对象传递给 ChannelHandler 解决了我的问题。因此,一旦通道处理程序断开连接,我就使用引导对象进行重新连接。谢谢 Veebs。
    猜你喜欢
    • 2012-04-10
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2011-02-05
    相关资源
    最近更新 更多