com.github.luohaha.handler.IoHandler Maven / Gradle / Ivy
package com.github.luohaha.handler;
import java.io.IOException;
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.logging.Logger;
import com.github.luohaha.connection.Connection;
import com.github.luohaha.connection.DataBag;
import com.github.luohaha.context.Context;
import com.github.luohaha.context.ContextBean;
import com.github.luohaha.inter.OnClose;
import com.github.luohaha.inter.OnRead;
import com.github.luohaha.inter.OnWrite;
public class IoHandler {
private Logger logger = Logger.getLogger("LightComm4J");
private Context context;
private Selector selector;
private static final int BUFFER_SIZE = 1024;
public IoHandler(Selector selector, Context context) {
super();
this.context = context;
this.selector = selector;
}
/**
* read data from remote site by channel
*
* @param channel
* channel
* @param onRead
* onRead
* @param onClose
* onClose
* @throws IOException
* ioexception
*/
public void readDataFromRemoteSite(SocketChannel channel, OnRead onRead, OnClose onClose) throws IOException {
// store current data
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
ContextBean bean = this.context.getChanToContextBean().get(channel);
// read from remote side
int count = channel.read(buffer);
if (count >= 0) {
// set buffer's position to 0
buffer.flip();
while (buffer.hasRemaining()) {
DataBag bag = bean.getReadyToRead();
bag.readFrom(buffer);
if (bag.isFinish()) {
// finish read one data bag
bean.getAlreadyReadData().add(bag.getBytes());
bean.setReadyToRead(new DataBag());
}
}
// call user's custom function
Queue dataQueue = bean.getAlreadyReadData();
while (!dataQueue.isEmpty()) {
onRead.onRead(bean.getConnection(), dataQueue.poll());
}
} else {
// read end
try {
closeRead(channel);
} catch (ClosedChannelException e) {
this.logger.warning("[Read Event] : " + e.toString());
throw new IOException();
}
if (onClose != null)
onClose.onClose(bean.getConnection());
}
}
/**
* write data to remote site
*
* @param channel
* channnel
* @param onWrite
* onWrite
* @throws IOException
* IOException
*/
public void writeDataToRemoteSite(SocketChannel channel, OnWrite onWrite) throws IOException {
ContextBean bean = this.context.getChanToContextBean().get(channel);
Connection connection = bean.getConnection();
// call write function when user define such function and haven't call
// it yet!
if (onWrite != null && !connection.isOnWriteCalled()) {
connection.setOnWriteCalled(true);
onWrite.onWrite(connection);
}
ByteBuffer buffer = connection.getReadyToWrite().peek();
if (buffer != null) {
if (buffer.hasRemaining()) {
channel.write(buffer);
}
// if this buffer finish write to buffer, delete it from queue
if (!buffer.hasRemaining()) {
connection.getReadyToWrite().poll();
}
}
// nothing to write
if (connection.getReadyToWrite().isEmpty()) {
try {
closeWrite(channel);
} catch (ClosedChannelException e) {
this.logger.warning("[Write Event] : " + e.toString());
throw new IOException();
}
if (connection.isReadyToClose()) {
connection.doClose();
}
return;
}
}
/**
* close write event
*
* @param channel
* channel
* @throws ClosedChannelException
* ClosedChannelException
*/
private void closeWrite(SocketChannel channel) throws ClosedChannelException {
closeOps(channel, SelectionKey.OP_WRITE);
}
/**
* close read event
*
* @param channel
* channel
* @throws ClosedChannelException
* ClosedChannelException
*/
private void closeRead(SocketChannel channel) throws ClosedChannelException {
closeOps(channel, SelectionKey.OP_READ);
}
/**
* close some operations
*
* @param channel
* channel
* @param opsToClose
* opsToClose
* @throws ClosedChannelException
* ClosedChannelException
*/
private void closeOps(SocketChannel channel, int opsToClose) throws ClosedChannelException {
ContextBean bean = this.context.getChanToContextBean().get(channel);
int ops = bean.getOps();
ops = (~opsToClose) & ops;
bean.setOps(ops);
channel.register(this.selector, ops);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy