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

hprose.net.Connection Maven / Gradle / Ivy

Go to download

Hprose is a High Performance Remote Object Service Engine. It is a modern, lightweight, cross-language, cross-platform, object-oriented, high performance, remote dynamic communication middleware. It is not only easy to use, but powerful. You just need a little time to learn, then you can use it to easily construct cross language cross platform distributed application system. Hprose supports many programming languages, for example: * AAuto Quicker * ActionScript * ASP * C++ * Dart * Delphi/Free Pascal * dotNET(C#, Visual Basic...) * Golang * Java * JavaScript * Node.js * Objective-C * Perl * PHP * Python * Ruby * ... Through Hprose, You can conveniently and efficiently intercommunicate between those programming languages. This project is the implementation of Hprose for Java.

There is a newer version: 2.0.38
Show newest version
/**********************************************************\
|                                                          |
|                          hprose                          |
|                                                          |
| Official WebSite: http://www.hprose.com/                 |
|                   http://www.hprose.org/                 |
|                                                          |
\**********************************************************/
/**********************************************************\
 *                                                        *
 * Connection.java                                        *
 *                                                        *
 * hprose Connection interface for Java.                  *
 *                                                        *
 * LastModified: Sep 19, 2016                             *
 * Author: Ma Bingyao                   *
 *                                                        *
\**********************************************************/
package hprose.net;

import hprose.io.ByteBufferStream;
import hprose.util.concurrent.Timer;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ClosedChannelException;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

public final class Connection {
    private final SocketChannel channel;
    private final ConnectionHandler handler;
    private final InetSocketAddress address;
    private volatile SelectionKey key;
    private volatile TimeoutType timeoutType;
    private final Timer timer = new Timer(new Runnable() {
        public void run() {
            try {
                handler.onTimeout(Connection.this, timeoutType);
            }
            finally {
                close();
            }
        }
    });
    private ByteBuffer inbuf = ByteBufferStream.allocate(1024);
    private int headerLength = 4;
    private int dataLength = -1;
    private Integer id = null;
    private OutPacket packet = null;
    private final Queue outqueue = new ConcurrentLinkedQueue();
    private Reactor reactor = null;
    public Connection(SocketChannel channel, ConnectionHandler handler, InetSocketAddress address) {
        this.channel = channel;
        this.handler = handler;
        this.address = address;
    }

    public final void connect(Selector selector) throws ClosedChannelException, IOException {
        key = channel.register(selector, SelectionKey.OP_CONNECT, this);
        setTimeout(handler.getConnectTimeout(), TimeoutType.CONNECT_TIMEOUT);
        channel.connect(address);
    }

    public final void connected(Reactor reactor, Selector selector) throws ClosedChannelException {
        clearTimeout();
        this.reactor = reactor;
        key = channel.register(selector, SelectionKey.OP_READ, this);
        handler.onConnected(this);
    }

    public final boolean isConnected() {
        return channel.isOpen() && channel.isConnected();
    }

    public final SocketChannel socketChannel() {
        return channel;
    }

    public final void close() {
        try {
            clearTimeout();
            handler.onClose(this);
            channel.close();
            key.cancel();
        }
        catch (IOException e) {}
    }

    public final boolean receive() {
        try {
            setTimeout(handler.getReadTimeout(), TimeoutType.READ_TIMEOUT);
            int n = channel.read(inbuf);
            if (n < 0) {
                close();
                return false;
            }
            if (n == 0) return true;
            for (;;) {
                if ((dataLength < 0) &&
                    (inbuf.position() >= headerLength)) {
                    dataLength = inbuf.getInt(0);
                    if (dataLength < 0) {
                        dataLength &= 0x7fffffff;
                        headerLength = 8;
                    }
                    if (headerLength + dataLength > inbuf.capacity()) {
                        ByteBuffer buf = ByteBufferStream.allocate(headerLength + dataLength);
                        inbuf.flip();
                        buf.put(inbuf);
                        ByteBufferStream.free(inbuf);
                        inbuf = buf;
                    }
                    setTimeout(handler.getReadTimeout(), TimeoutType.READ_TIMEOUT);
                    if (channel.read(inbuf) < 0) {
                        close();
                        return false;
                    }
                }
                if ((headerLength == 8) && (id == null)
                    && (inbuf.position() >= headerLength)) {
                    id = inbuf.getInt(4);
                }
                if ((dataLength >= 0) &&
                    ((inbuf.position() - headerLength) >= dataLength)) {
                    ByteBuffer data = ByteBufferStream.allocate(dataLength);
                    inbuf.flip();
                    inbuf.position(headerLength);
                    int bufLen = inbuf.limit();
                    inbuf.limit(headerLength + dataLength);
                    data.put(inbuf);
                    inbuf.limit(bufLen);
                    inbuf.compact();
                    clearTimeout();
                    handler.onReceived(this, data, id);
                    headerLength = 4;
                    dataLength = -1;
                    id = null;
                }
                else {
                    break;
                }
            }
        }
        catch (Exception e) {
            handler.onError(this, e);
            close();
            return false;
        }
        return true;
    }

    public final void send(ByteBuffer buffer, Integer id) {
        outqueue.offer(new OutPacket(buffer, id));
        key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
        reactor.write(this);
    }

    public final void send() {
        if (packet == null) {
            packet = outqueue.poll();
            if (packet == null) {
                return;
            }
        }
        try {
            for (;;) {
                while (packet.writeLength < packet.totalLength) {
                    setTimeout(handler.getWriteTimeout(), TimeoutType.WRITE_TIMEOUT);
                    long n = channel.write(packet.buffers);
                    if (n < 0) {
                        close();
                        return;
                    }
                    if (n == 0) {
                        key.interestOps(SelectionKey.OP_READ | SelectionKey.OP_WRITE);
                        return;
                    }
                    packet.writeLength += n;
                }
                ByteBufferStream.free(packet.buffers[1]);
                clearTimeout();
                handler.onSended(this, packet.id);
                synchronized (outqueue) {
                    packet = outqueue.poll();
                    if (packet == null) {
                        key.interestOps(SelectionKey.OP_READ);
                        return;
                    }
                }
            }
        }
        catch (Exception e) {
            close();
        }
    }

    public final void setTimeout(int timeout, TimeoutType type) {
        timeoutType = type;
        if (type == TimeoutType.IDLE_TIMEOUT) {
            timer.setTimeout(timeout);
        }
        else {
            timer.setTimeout(timeout, true);
        }
    }

    public final void clearTimeout() {
        timer.clear();
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy