package org.fanhongtao.middleman.client;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.fanhongtao.middleman.core.AsyncObject;
/**
* 实现异步的客户端
* @author Dharma
* @created 2008-11-26
*/
class AsyncClient extends AsyncObject implements Runnable
{
private static Logger logger = Logger.getLogger(AsyncClient.class);
/**
* 与服务器之间的链接
*/
private SocketChannel clientChannel;
/**
* 服务器IP
*/
private String host;
/**
* 服务器端口
*/
private int port;
/**
* 待发送消息的队列
*/
private ArrayList<byte[]> sendList = new ArrayList<byte[]>();
public AsyncClient(String host, int port)
{
this.host = host;
this.port = port;
}
public void run()
{
logger.info("Try to connect to " + host + " : " + port);
try
{
// 生成一个socketchannel, 并连接到 Server
InetSocketAddress addr = new InetSocketAddress(host, port);
clientChannel = SocketChannel.open(addr);
logger.info("connection has been established, local port is " + clientChannel.socket().getLocalPort());
clientChannel.configureBlocking(false); // 设置为非阻塞方式
Selector selector = Selector.open(); // 生成一个信号监视器
clientChannel.register(selector, SelectionKey.OP_READ);
while (!isQuit())
{
if (selector.select(1000) != 0)
{
logger.trace("event occur");
processIOEvent(selector);
}
else
{
logger.trace("time out");
}
sendMessage();
}
logger.info("Disconnect with " + host + ":" + port);
clientChannel.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* 将发送队列中的消息发送出去
* @throws IOException
*/
private void sendMessage() throws IOException
{
synchronized (sendList)
{
if (sendList.size() > 0)
{
// 每次只发送一个消息,以防止产生的消息太多
byte[] msg = sendList.remove(0);
writeBuffer.clear();
writeBuffer.put(msg);
writeBuffer.flip();
logWritedMessage(clientChannel);
// 发送消息
while (writeBuffer.hasRemaining())
{
clientChannel.write(writeBuffer);
}
writeBuffer.clear();
}
}
}
public void sendMessage(byte[] bytes)
{
synchronized (sendList)
{
sendList.add(bytes);
}
}
/**
* 处理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.isReadable())
{
logger.trace("Receive date from server");
receiveFromServer();
}
iterator.remove();
}
}
/**
* 读取server端发回的数据,并显示
*
* @throws IOException
*/
public void receiveFromServer() throws IOException
{
readBuffer.clear();
int count = clientChannel.read(readBuffer);
readBuffer.flip();
logReceivedMessage(clientChannel);
byte[] temp = new byte[readBuffer.limit()];
readBuffer.get(temp);
logger.info("reply is " + count + " bytes long, and content is: " + new String(temp));
}
public static void main(String args[])
{
String host = "127.0.0.1";
int port = 3456;
BasicConfigurator.configure();
if (args.length == 1)
{
host = args[0];
}
else if (args.length > 1)
{
host = args[0];
port = Integer.parseInt(args[1]);
}
new AsyncClient(host, port).run();
}
}