All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.appconn.channel.TcpClient Maven / Gradle / Ivy

Go to download

Java library for easy and fast implementation of distributed applications, including, optimized serialization, high availability administration and server resources management.

There is a newer version: 1.2
Show newest version
package org.appconn.channel;

import java.io.IOException;
import java.net.SocketAddress;
import java.nio.channels.ClosedSelectorException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * appconn AbstractClient TCP implementation.
 */
final class TcpClient extends AbstractClient {

    private final SocketChannel channel;
    private final Selector selector;

    /**
     * Constructs a new TcpClient.
     * @param remote            the remote SocketAddress
     * @param connectTimeout    the connectTimeout in millis
     * @param keepAlive         the keepAlive
     * @param readBufferLength  the readBufferLength
     * @param writeBufferLength the writeBufferLength
     * @param returns           the Returns implementation instance
     * @throws IOException if an I/O exception of some sort has occurred
     */
    TcpClient(SocketAddress remote, int connectTimeout, boolean keepAlive, int readBufferLength, int writeBufferLength, Returns returns) throws IOException {
        super(TcpClient.class.getName());

        channel = SocketChannel.open();
        channel.socket().connect(remote, connectTimeout);
        channel.socket().setKeepAlive(keepAlive);
        channel.socket().setTcpNoDelay(true);
        channel.configureBlocking(false);

        readBuffer = new ReadHeapByteBuffer(channel, readBufferLength);
        writeBuffer = new WriteHeapByteBuffer(channel, writeBufferLength);

        selector = Selector.open();
        channel.register(selector, SelectionKey.OP_READ, new ClientHandler(channel));

        this.returns = returns;

        start();
        Logger.getLogger("org.appconn").log(Level.FINE, "connected to " + channel.getRemoteAddress());
    }

    @Override
    public void run() {
        while (true) {
            try {
                selector.select();
                Iterator iterator = selector.selectedKeys().iterator();
                while (iterator.hasNext()) {
                    SelectionKey selectionKey = iterator.next();
                    iterator.remove();
                    ((Handler) selectionKey.attachment()).handle();
                }
            } catch (IOException e) {
                Logger.getLogger("org.appconn").log(Level.WARNING, e, e::getMessage);
                break;
            } catch (ClosedSelectorException e) {
                break;
            }
        }
    }

    @Override
    public void interrupt() {
        try {
            close();
        } catch (IOException e) {
            Logger.getLogger("org.appconn").log(Level.CONFIG, "interrupt", e);
        }
    }

    @Override
    public void close() throws IOException {
        selector.close();
        channel.close();
        super.interrupt();
    }

    private class ClientHandler implements Handler {

        private final SocketChannel channel;

        private ClientHandler(SocketChannel channel) {
            this.channel = channel;
        }

        @Override
        public synchronized void handle() {
            try {
                readBuffer.read();
                while (readBuffer.hasRemaining()) {
                    int position = readBuffer.getInt();
                    MethodReturn methodReturn = remove(position);
                    if (methodReturn != null) {
                        if (readBuffer.get() == Writer.IS_RETURN) methodReturn.setReturn(readBuffer);
                        else {
                            String className = TypeReader.STRING_READER.get(readBuffer);
                            Throwable throwable = TypeReader.THROWABLE_READER.get(readBuffer);

                            Exception exception = (Exception) Class.forName(className).getConstructor(String.class).newInstance(throwable.getMessage());
                            exception.setStackTrace(throwable.getStackTrace());
                            methodReturn.setException(exception);
                        }
                    } else {
                        Logger.getLogger("org.appconn").log(Level.WARNING, "null methodReturn position " + position);
                        channel.close();
                    }
                }
            } catch (Exception e) {
                Logger.getLogger("org.appconn").log(Level.WARNING, e, e::getMessage);
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy