dk.dma.ais.bus.provider.TcpClientProvider.java Source code

Java tutorial

Introduction

Here is the source code for dk.dma.ais.bus.provider.TcpClientProvider.java

Source

/* Copyright (c) 2011 Danish Maritime Authority.
 *
 * Licensed under the Apache License, Version 2.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.apache.org/licenses/LICENSE-2.0
 *
 * 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 dk.dma.ais.bus.provider;

import dk.dma.ais.bus.AisBusProvider;
import dk.dma.ais.bus.tcp.IClientStoppedListener;
import dk.dma.ais.bus.tcp.TcpClient;
import dk.dma.ais.bus.tcp.TcpClientConf;
import dk.dma.ais.bus.tcp.TcpReadClient;
import dk.dma.ais.packet.AisPacket;
import net.jcip.annotations.ThreadSafe;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

/**
 * Round robin TCP client provider
 */
@ThreadSafe
public final class TcpClientProvider extends AisBusProvider
        implements Runnable, Consumer<AisPacket>, IClientStoppedListener {

    private static final Logger LOG = LoggerFactory.getLogger(TcpClientProvider.class);

    private TcpReadClient readClient;

    private TcpClientConf clientConf = new TcpClientConf();
    private List<String> hostsPorts = new ArrayList<>();
    private int reconnectInterval = 10;
    private int timeout = 10;

    private List<String> hostnames = new ArrayList<>();
    private List<Integer> ports = new ArrayList<>();
    private int currentHost = -1;
    private volatile Socket socket;

    public TcpClientProvider() {
        super();
    }

    @Override
    public void run() {
        setNotConnected();
        while (true) {
            socket = new Socket();

            // Get next host and port
            selectHost();
            String host = hostnames.get(currentHost);
            int port = ports.get(currentHost);

            // Connect
            try {
                InetSocketAddress address = new InetSocketAddress(host, port);
                LOG.info("Connecting to " + host + ":" + port + " ...");
                socket.connect(address);
                socket.setKeepAlive(true);
                if (timeout > 0) {
                    socket.setSoTimeout(timeout * 1000);
                }

                setConnected();

                // Start client
                readClient = new TcpReadClient(this, this, socket, clientConf);
                readClient.start();
                // Wait for client to loose connection
                readClient.join();
                readClient = null;
            } catch (IOException e) {
                LOG.info(getName() + ": connection error: " + e.getMessage());
            } catch (InterruptedException e) {
                readClient.cancel();
                break;
            }

            setNotConnected();

            try {
                LOG.info("Waiting to reconnect");
                Thread.sleep(reconnectInterval * 1000);
            } catch (InterruptedException e) {
                break;
            }

        }

        setStopped();
    }

    @Override
    public void accept(AisPacket packet) {
        push(packet);
    }

    @Override
    public synchronized void start() {
        // Start self as thread
        Thread t = new Thread(this);
        setThread(t);
        t.start();
        super.start();
    }

    @Override
    public void cancel() {
        // Close socket
        Socket s = socket;
        if (s != null) {
            try {
                s.close();
            } catch (IOException ignore) {
            }
        }
        getThread().interrupt();
        try {
            getThread().join(THREAD_STOP_WAIT_MAX);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        setStopped();
    }

    @Override
    public synchronized void init() {
        for (String hostPort : hostsPorts) {
            String[] parts = StringUtils.split(hostPort, ':');
            hostnames.add(parts[0]);
            ports.add(Integer.parseInt(parts[1]));
        }
        super.init();
    }

    public List<String> getHostsPorts() {
        return hostsPorts;
    }

    public void setHostsPorts(List<String> hostsPorts) {
        this.hostsPorts = hostsPorts;
    }

    public void setClientConf(TcpClientConf clientConf) {
        this.clientConf = clientConf;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public void setReconnectInterval(int reconnectInterval) {
        this.reconnectInterval = reconnectInterval;
    }

    @Override
    public void clientStopped(TcpClient client) {

    }

    private void selectHost() {
        currentHost = (currentHost + 1) % hostnames.size();
    }

}