package org.fanhongtao.middleman.server;
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 org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.fanhongtao.middleman.core.AsyncObject;
import org.fanhongtao.middleman.core.IMessageWindow;
/**
* 只接收消息,不给客户端回复任何消息。
*
* @author Dharma
* @created 2008-10-29
*/
public class MuteServer extends AsyncObject implements Runnable
{
private static Logger logger = Logger.getLogger(MuteServer.class);
/** 服务端口 */
private int port = 0;
private ServerSocketChannel serverChannel = null;
Selector selector = null;
public MuteServer(int port, IMessageWindow logWindow)
{
this.port = port;
this.logWindow = logWindow;
}
public boolean bind()
{
logger.info("Try to start server with port " + port);
// 生成一个侦听端
try
{
serverChannel = ServerSocketChannel.open();
serverChannel.configureBlocking(false); // 将侦听端设为异步方式
// 侦听端绑定到一个端口
serverChannel.socket().bind(new InetSocketAddress(port));
}
catch (IOException e)
{
e.printStackTrace();
logger.warn("Failed to start server. " + e.getLocalizedMessage());
return false;
}
logger.info("echo server has been set up ......");
return true;
}
public void run()
{
logger.debug("Try to accept client...");
try
{
selector = Selector.open(); // 生成一个信号监视器
// 设置侦听端所选的异步信号OP_ACCEPT, 这样才能够新的连接
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
int count = 0;
while (!isQuit())
{
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)
{
e.printStackTrace();
}
}
/**
* 处理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())
{
// 侦听端信号触发
ServerSocketChannel server = (ServerSocketChannel) key.channel();
// 接受一个新的连接
SocketChannel client = server.accept();
client.configureBlocking(false);
// 设置该socket的异步信号OP_READ
// 当socket中有数据时,会触发 processIOEvent
// 通过 key.isReadable() 判断,最终调用 receiveDataFromClient()
client.register(selector, SelectionKey.OP_READ);
onAccept(client);
logger.info("Accept a client , port is " + client.socket().getPort());
}
if (key.isReadable())
{
logger.debug("Receive date from client");
// 某socket可读信号
receiveDataFromClient(key);
}
iterator.remove();
}
}
/**
* 获得一个客户端的链接
* @param client
*/
protected void onAccept(SocketChannel client)
{
}
/**
* 处理来自客户端的消息
*
* @param key 代表对应的客户端
*
*/
public void receiveDataFromClient(SelectionKey key)
{
// 由key获取指定socketchannel的引用
SocketChannel clientChannel = (SocketChannel) key.channel();
readBuffer.clear();
try
{
// 读取数据到readBuffer
while (clientChannel.read(readBuffer) > 0)
{
; // do nothing
}
// 确保 readBuffer 可读
readBuffer.flip();
// 读入字节为0, 则认为是客户端已经断连
if (readBuffer.limit() == 0)
{
throw new IOException("Read 0 bytes from socket.");
}
// 将接收到的消息记录下来
logReceivedMessage(clientChannel);
/*
* // 将 readBuffer 内容拷入 writeBuffer
writeBuffer.clear();
writeBuffer.put(readBuffer);
writeBuffer.flip();
// 将数据返回给客户端
while (writeBuffer.hasRemaining())
{
clientChannel.write(writeBuffer);
}
*/
}
catch (IOException e)
{
e.printStackTrace();
logger.info("close a client , port is " + clientChannel.socket().getPort());
key.cancel();
try
{
key.channel().close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
}
/**
* @param args
*/
public static void main(String[] args)
{
BasicConfigurator.configure(); // 使用缺省配置
int port = 8088;
if (args.length == 1)
{
port = Integer.parseInt(args[0]);
}
MuteServer server = new MuteServer(port, null);
if (server.bind())
{
new Thread(server).start();
}
}
}