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

cn.tom.transport.aio.AioClient Maven / Gradle / Ivy

The newest version!
package cn.tom.transport.aio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.StandardSocketOptions;
import java.nio.channels.AsynchronousChannelGroup;
import java.nio.channels.AsynchronousSocketChannel;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import cn.tom.kit.ThreadPool;
import cn.tom.kit.ThreadPool.DefaultThreadFactory;
import cn.tom.transport.Client;
import cn.tom.transport.Id;
import cn.tom.transport.IoAdaptor;
import cn.tom.transport.Ticket;
import cn.tom.transport.Messager.MessageCallback;


public class AioClient implements Client{
	private static final Logger log = LoggerFactory.getLogger(AioClient.class);
	protected final String brokerAddress;
	private int readTimeout = 20000;
	
	private String host = "127.0.0.1";
	private int port = 15555;
	
	private IoAdaptor ioAdaptor;
	public AioSession	session;
	

	public AioClient(String address) throws IOException {
		this.brokerAddress = address;
		String[] blocks = address.split("[:]");
		if (blocks.length > 2) {
			throw new IllegalArgumentException("Illegal address: " + address);
		}
		String host = blocks[0].trim();
		this.host = host;
		int port = 15555;
		if (blocks.length > 1) {
			port = Integer.valueOf(blocks[1].trim());
		}
		this.port = port;
	}
	
	public AioClient(String host, int port) {
		this.host = host;
		this.port = port;
		this.brokerAddress = String.format("%s:%d", host, port);
	}
	
	@Override
	public void heartbeat() {
		if(hasConnected()){
			ioAdaptor.heartbeat(session);
		}
	}

	@Override
	public void doConnect() throws IOException {
		// client 至少 2个线程, 1个线程的话可能频繁写没有线程读死锁
		AsynchronousChannelGroup asynchronousChannelGroup = AsynchronousChannelGroup.withFixedThreadPool(2, new DefaultThreadFactory("AioClient-pool-"));
		AsynchronousSocketChannel socketChannel = AsynchronousSocketChannel.open(asynchronousChannelGroup);
		socketChannel.setOption(StandardSocketOptions.TCP_NODELAY, true);
		socketChannel.setOption(StandardSocketOptions.SO_REUSEADDR, true);
		socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, true);
		session = new AioSession(ioAdaptor, socketChannel);
		ConnectedHandler connectedCompletionHandler = new ConnectedHandler();
		InetSocketAddress socketAddress = new InetSocketAddress(this.host, this.port);
		socketChannel.connect(socketAddress, session, connectedCompletionHandler);
		session.waitToConnect(20000);
	}

	/**
	 * 异步访问, client少量, 重点在于处理与回调
	 * write 不等待加大了 buffer读写区
	 */
	@Override
	public void invokeAsync(T req, MessageCallback callback) throws IOException {
		connectIfNeed();
		ioAdaptor.createTicket(req, readTimeout*10, callback);
		session.write(req);
	}

	/**
	 * 同步访问, 增加client数量, 性能加大, 
	 * 看buffer的大小,由于同步, 多client 加大了buffer读写区
	 */
	@Override
	public T invokeSync(T req) throws IOException, InterruptedException {
		return invokeSync(req, readTimeout);
	}
	

	public T invokeSync(T req, int timeout) throws IOException, InterruptedException {
    	Ticket ticket = null; 
		try {
			connectIfNeed();
			ticket = ioAdaptor.createTicket(req, timeout, null); 
			session.write(req);
			if(!ticket.await(timeout, TimeUnit.MILLISECONDS)){
				if(!session.isActive()){
					throw new IOException("Connection reset by peer");
				} else {
					return null;
				}
			}
		    return (T) ticket.response(); 
		} finally{
			if(ticket != null){
				ioAdaptor.removeTicket(ticket.getId());
			}
		}   
    } 

	@Override
	public void send(T msg) throws IOException {
		connectIfNeed();
		session.write(msg);
	}

	@Override
	public void setIoAdaptor(IoAdaptor ioAdaptor) {
		this.ioAdaptor = ioAdaptor;
	}
	

	public  void connectIfNeed() throws IOException {
		if (!this.hasConnected()) {
			synchronized (brokerAddress) {
				if(!this.hasConnected()){
					doConnect();
					heartbeat();
				}
			}
		}
	}
	
	@Override
	public boolean hasConnected() {
		return session != null && session.isActive();
	}
	
	@Override
	public void close() throws IOException {
		if (this.session != null) {
			this.session.close();
		}
		ThreadPool.getAioPool().shutdown();
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy