org.tinygroup.nettyremote.impl.ClientImpl.java Source code

Java tutorial

Introduction

Here is the source code for org.tinygroup.nettyremote.impl.ClientImpl.java

Source

/**
 *  Copyright (c) 1997-2013, www.tinygroup.org (luo_guo@icloud.com).
 *
 *  Licensed under the GPL, Version 3.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *       http://www.gnu.org/licenses/gpl.html
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package org.tinygroup.nettyremote.impl;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPromise;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.serialization.ClassResolvers;
import io.netty.handler.codec.serialization.ObjectDecoder;
import io.netty.handler.codec.serialization.ObjectEncoder;
import io.netty.util.concurrent.Future;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.tinygroup.event.Event;
import org.tinygroup.logger.LogLevel;
import org.tinygroup.logger.Logger;
import org.tinygroup.logger.LoggerFactory;
import org.tinygroup.nettyremote.Client;
import org.tinygroup.nettyremote.DisconnectCallBack;
import org.tinygroup.nettyremote.Exception.TinyRemoteConnectException;

public class ClientImpl implements Client {
    private static final Logger LOGGER = LoggerFactory.getLogger(ClientImpl.class);
    private ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
    private EventLoopGroup group = new NioEventLoopGroup();
    private int remotePort;// ??
    private String remoteHost;// ??
    private boolean ready;// ??
    private boolean start = false;// ??
    private boolean reConnect = false;// ?,???
    private int reConnectInterval = 10; // ??:
    private DisconnectCallBack callBack;

    private ClientThread clientThread = new ClientThread();
    private ChannelFuture future;

    public ClientImpl(int remotePort, String remoteHost, boolean reConnect) {
        this.remotePort = remotePort;
        this.remoteHost = remoteHost;
        this.reConnect = reConnect;
    }

    public void start() {
        LOGGER.logMessage(LogLevel.INFO, "??{0}:{1}", remoteHost, remotePort);
        start = false;
        clientThread.start();

    }

    public void write(Object o) {
        if (o instanceof Event) {
            Event event = (Event) o;
            LOGGER.logMessage(LogLevel.DEBUG, "?:eventId:{},serviceId:{}", event.getEventId(),
                    event.getServiceRequest().getServiceId());
        }
        if (future == null || future.channel() == null) {
            throw new RuntimeException("");
        }
        ChannelFuture f = future.channel().writeAndFlush(o);
        if (f instanceof ChannelPromise) {
            ChannelPromise p = (ChannelPromise) f;
            try {
                p.await();
            } catch (InterruptedException e) {
                LOGGER.logMessage(LogLevel.WARN, "?");
            }
            if (p.isSuccess()) {
                LOGGER.logMessage(LogLevel.DEBUG, "??{}", p.isSuccess());
            } else {
                LOGGER.logMessage(LogLevel.WARN, "??false");
                throw new RuntimeException(p.cause());
            }

        }

    }

    private void reConnect() {
        if (!executor.isShutdown()) {
            // ????????
            executor.execute(new Runnable() {
                public void run() {
                    try {
                        TimeUnit.SECONDS.sleep(reConnectInterval);
                        LOGGER.logMessage(LogLevel.INFO, "??{0}:{1}", remoteHost, remotePort);
                        connect(remotePort, remoteHost);// ???
                    } catch (InterruptedException e) {
                        // do nothing
                    }
                }
            });
        }

    }

    private void connect(int port, String host) {
        // ?NIO
        try {
            Bootstrap b = new Bootstrap();
            b.group(group);
            init(b);
            // ??
            future = b.connect(host, port).sync();
            future.channel().closeFuture().sync();
        } catch (Exception e) {
            LOGGER.errorMessage("?{0}:{1}?", e, remoteHost, remotePort);
            if (!reConnect) {
                throw new TinyRemoteConnectException(
                        "?" + remoteHost + ":" + remotePort + "?", e);
            }
        } finally {
            if (reConnect && start) {
                reConnect();
            }
        }
        if (callBack != null) {
            callBack.call();
        }
    }

    protected void init(Bootstrap b) {
        b.channel(NioSocketChannel.class).option(ChannelOption.TCP_NODELAY, true)
                .handler(new ChannelInitializer<SocketChannel>() {
                    public void initChannel(SocketChannel ch) throws Exception {
                        ch.pipeline().addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(null)));
                        ch.pipeline().addLast("MessageEncoder", new ObjectEncoder());
                        ch.pipeline().addLast(new ClientHandler());
                    }
                });

    }

    class ClientThread extends Thread {
        public void run() {
            if (!start) {
                start = true;
                LOGGER.logMessage(LogLevel.INFO, "?{0}:{1}", remoteHost, remotePort);
                connect(remotePort, remoteHost);
            }

        }
    }

    public void stop() {
        LOGGER.logMessage(LogLevel.INFO, "");
        if (reConnect == true) {
            reConnect = false;
            try {
                executor.shutdownNow();
            } catch (Exception e) {
                LOGGER.errorMessage("?", e);
            }

        }
        start = false;
        Future wg = null;
        try {
            wg = group.shutdownGracefully();
        } catch (Exception e) {
            LOGGER.errorMessage("Client", e);
        }

        try {
            if (wg != null) {
                wg.await();
            }
        } catch (InterruptedException e) {
            LOGGER.logMessage(LogLevel.INFO, "EventLoopGroup shutdownGracefully");
        }

        setReady(false);
        LOGGER.logMessage(LogLevel.INFO, "?");
    }

    public void doReady() {
        setReady(true);
        LOGGER.logMessage(LogLevel.INFO, "?{0}:{1}", remoteHost, remotePort);
    }

    public boolean isReady() {
        if (future == null || future.channel() == null) {
            return false;
        }
        return ready;
    }

    public void setReady(boolean ready) {
        this.ready = ready;
    }

    public int getRemotePort() {
        return remotePort;
    }

    public void setRemotePort(int remotePort) {
        this.remotePort = remotePort;
    }

    public String getRemoteHost() {
        return remoteHost;
    }

    public void setRemoteHost(String remoteHost) {
        this.remoteHost = remoteHost;
    }

    public void setCallBack(DisconnectCallBack callBack) {
        this.callBack = callBack;
    }

}