Netty 自動重連

from: http://www.dozer.cc/2015/05/netty-auto-reconnect.htmlhtml

 

自動重連

用 Netty 寫 Client 和 Server 的時候必需要去處理自動重連。java

Server 端啓動時的錯誤,要去不斷重試。git

Client 端不只要處理啓動時的錯誤,還要處理中途斷開鏈接。github

 

Server 端的處理

和常規的代碼相比,Server 端只要處理一個地方便可:bootstrap

public final class TcpServer {         private volatile EventLoopGroup bossGroup;      private volatile EventLoopGroup workerGroup;      private volatile ServerBootstrap bootstrap;      private volatile boolean closed = false;      private final int localPort;      public TcpServer(int localPort) {         this.localPort = localPort;     }      public void close() {         closed = true;          bossGroup.shutdownGracefully();         workerGroup.shutdownGracefully();          System.out.println("Stopped Tcp Server: " + localPort);     }      public void init() {         closed = false;          bossGroup = new NioEventLoopGroup();         workerGroup = new NioEventLoopGroup();         bootstrap = new ServerBootstrap();         bootstrap.group(bossGroup, workerGroup);          bootstrap.channel(NioServerSocketChannel.class);          bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {             @Override             protected void initChannel(SocketChannel ch) throws Exception {                 //todo: add more handler             }         });          doBind();     }      protected void doBind() {         if (closed) {             return;         }          bootstrap.bind(localPort).addListener(new ChannelFutureListener() {             @Override             public void operationComplete(ChannelFuture f) throws Exception {                 if (f.isSuccess()) {                     System.out.println("Started Tcp Server: " + localPort);                 } else {                     System.out.println("Started Tcp Server Failed: " + localPort);                      f.channel().eventLoop().schedule(() -> doBind(), 1, TimeUnit.SECONDS);                 }             }         });     } }

咱們把整個初始化分紅了兩個部分,第一部分是初始化相關 class,第二部分作真正的監聽端口。ide

這裏最特殊的地方就是在調用bind方法後,添加一個listener檢查是否成功,若是失敗的話,須要調用.channel().eventLoop().schedule()方法,建立一個任務,我這代碼設置的是1秒後嘗試從新鏈接。oop

另外考慮到 server 能夠被人爲關閉,因此還須要檢查當前時候已經關閉。若是不檢查的話,你的 server 可能就永遠也關不掉了。this

 

Client 端的處理

client 端啓動流程差很少,可是須要加一個 handler 來處理鏈接斷開。spa

public class TcpClient {      private volatile EventLoopGroup workerGroup;      private volatile Bootstrap bootstrap;      private volatile boolean closed = false;      private final String remoteHost;      private final int remotePort;      public TcpClient(String remoteHost, int remotePort) {         this.remoteHost = remoteHost;         this.remotePort = remotePort;     }      public void close() {         closed = true;         workerGroup.shutdownGracefully();         System.out.println("Stopped Tcp Client: " + getServerInfo());     }      public void init() {         closed = false;          workerGroup = new NioEventLoopGroup();         bootstrap = new Bootstrap();         bootstrap.group(workerGroup);         bootstrap.channel(NioSocketChannel.class);          bootstrap.handler(new ChannelInitializer<SocketChannel>() {             @Override             public void initChannel(SocketChannel ch) throws Exception {                 ChannelPipeline pipeline = ch.pipeline();                 pipeline.addFirst(new ChannelInboundHandlerAdapter() {                     @Override                     public void channelInactive(ChannelHandlerContext ctx) throws Exception {                         super.channelInactive(ctx);                         ctx.channel().eventLoop().schedule(() -> doConnect(), 1, TimeUnit.SECONDS);                     }                 });                  //todo: add more handler             }         });          doConnect();     }      private void doConnect() {         if (closed) {             return;         }          ChannelFuture future = bootstrap.connect(new InetSocketAddress(remoteHost, remotePort));          future.addListener(new ChannelFutureListener() {             public void operationComplete(ChannelFuture f) throws Exception {                 if (f.isSuccess()) {                     System.out.println("Started Tcp Client: " + getServerInfo());                 } else {                     System.out.println("Started Tcp Client Failed: " + getServerInfo());                     f.channel().eventLoop().schedule(() -> doConnect(), 1, TimeUnit.SECONDS);                 }             }         });     }      private String getServerInfo() {         return String.format("RemoteHost=%s RemotePort=%d",                 remotePort,                 remotePort);     } }

能夠看到,咱們在channelInactive事件中,也建立了一個任務,在1秒後從新鏈接。netty

 

示例代碼

你們能夠本身跑跑看:

https://github.com/dozer47528/AutoReconnectNettyExample

本做品由  Dozer 創做,採用  知識共享署名-非商業性使用 4.0 國際許可協議 進行許可。
相關文章
相關標籤/搜索