package org.fanhongtao.net.frame.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Timer;
import java.util.TimerTask;
import org.fanhongtao.log.RunLogger;
import org.fanhongtao.net.frame.handler.IHandler;
/**
* @author Dharma
* @created 2009-5-2
*/
public class Server
{
/** 服务端口 */
private int port = 0;
/** 响应Socket事件(建立连接、接收到消息、断开连接)的处理器 */
private IHandler handler = null;
private ServerSocketChannel serverChannel = null;
private Selector selector = null;
private Timer timer;
public Server(int port, IHandler handler)
{
this.port = port;
this.handler = handler;
}
public void init()
throws IOException
{
bind();
initTimer();
initThread();
RunLogger.info("Server has been set up ......");
}
private void bind()
throws IOException
{
RunLogger.info("Try to start server with port " + port);
// 生成一个侦听端
selector = Selector.open(); // 生成一个信号监视器
serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false); // 将侦听端设为异步方式
// 侦听端绑定到一个端口
serverChannel.socket().bind(new InetSocketAddress(port));
// 设置侦听端所选的异步信号OP_ACCEPT, 这样才能够新的连接
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
return;
}
private void initTimer()
{
timer = new Timer();
TimerTask task = new TimerTask()
{
@Override
public void run()
{
// synchronized (connMap)
// {
// Set<Entry<SocketChannel, Connection>> set =
// connMap.entrySet();
// Iterator<Entry<SocketChannel, Connection>> iter =
// set.iterator();
// while (iter.hasNext())
// {
// Entry<SocketChannel, Connection> entry = iter.next();
// Connection conn = entry.getValue();
// if (!conn.isExist())
// {
// iter.remove();
// }
// }
// }
}
};
timer.schedule(task, 1000, 1000);
}
/**
* 创建工作线程。
*/
private void initThread()
{
MessageHandler handler = new MessageHandler();
Thread thread = new Thread(handler, "handler");
thread.start();
for (int i = 1; i < 4; i++)
{
String name = "Reader-" + i;
ChannelReader reader = new ChannelReader();
reader.setName(name);
thread = new Thread(reader, name);
thread.start();
name = "Writer-" + i;
ChannelWriter writer = new ChannelWriter();
writer.setName(name);
thread = new Thread(writer, name);
thread.start();
}
}
public void run()
{
RunLogger.debug("Server is on services ...");
try
{
int count = 0;
while (true)
{
if (selector.select(1000) != 0)
{
// logger.debug("event occur");
processIOEvent(selector);
}
else
{
// 没有指定的I/O事件发生
count++;
if (count > 10)
{
// logger.debug("time out.....");
count = 0;
}
}
}
// serverChannel.close();
// logger.info("echo server has been shutdown ......");
}
catch (Exception e)
{
RunLogger.error("Error occured.", e);
}
}
/**
* 处理IO事件
*
* @param selector
* @throws IOException
*/
private void processIOEvent(Selector selector)
throws IOException
{
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while (iterator.hasNext())
{
SelectionKey key = iterator.next();
if (key.isAcceptable())
{
onAccept(key);
}
if (key.isReadable()) // 某socket有数据可以读取
{
// RunLogger.debug("Receive date from client: " + key);
ChannelReader.processRequest(key);
}
iterator.remove();
}
}
/**
* 获得一个客户端的链接
* @param client
* @throws IOException
*/
private void onAccept(SelectionKey key)
throws IOException
{
// 侦听端信号触发
ServerSocketChannel server = (ServerSocketChannel) key.channel();
// 接受一个新的连接
SocketChannel client = server.accept();
client.configureBlocking(false);
// 设置该socket的异步信号OP_READ
// 当socket中有数据时,会触发 processIOEvent,并满足 key.isReadable() 条件
SelectionKey clientKey = client.register(selector, SelectionKey.OP_READ);
Connection connection = new Connection(clientKey, handler);
clientKey.attach(connection);
RunLogger.info("Accept a client, " + connection.getRemoteAddress() + ", local port: "
+ connection.getLocalAddress().getPort());
try
{
handler.onAccept(connection);
}
catch (Exception e)
{
RunLogger.error("Failed to register handler", e);
}
}
}