4.AcceptHandler类
AcceptHandler负责处理接收连结就绪事件。它获得与客户连接的SocketChannel,然后向Selector注册读就绪事件,并且创建了一个RequestHandler,把它作为SelectionKey的附件。当读就绪事件发生,将由这个RequestHandler来处理该事件。例程4是AcceptHandler类的源程序:
//例程4 AcceptHandler.java
//此处省略import语句
public class AcceptHandler implements Handler {
public void handle(SelectionKey key) throws IOException {
ServerSocketChannel serverSocketChannel=(ServerSocketChannel)key.channel();
//在非阻塞模式下,serverSocketChannel.accept()有可能返回null
//判断socketChannel是否为null,可以使程序更加健壮,避免NullPointerException
SocketChannel socketChannel = serverSocketChannel.accept();
if (socketChannel== null)return;
System.out.println("接收到客户连接,来自:" +
socketChannel.socket().getInetAddress() +
":" + socketChannel.socket().getPort());
ChannelIO cio =new ChannelIO(socketChannel, false /*非阻塞模式*/);
RequestHandler rh = new RequestHandler(cio);
//注册读就绪事件,把RequestHandler作为附件,
//当这种事件发生时,将由RequestHandler处理该事件
socketChannel.register(key.selector(), SelectionKey.OP_READ, rh);
}
}
在以上AcceptHandler的handle()方法中,还创建了一个ChannelIO,RequestHandler与它关联。RequestHandler会利用ChannelIO来接收和发送数据。
5.RequestHandler类
RequestHandler先通过ChannelIO来接收HTTP请求,当接收到了HTTP请求的所有数据,就对HTTP请求数据进行解析,创建相应的Request对象,然后依据客户的请求内容,创建相应的Response对象,最后发送Response对象中包含的HTTP响应数据。为了简化程序,RequestHandler仅仅支持GET和HEAD这两种请求方式。例程5是RequestHandler的源程序:
//例程5 RequestHandler.java
//此处省略import语句
public class RequestHandler implements Handler {
private ChannelIO channelIO;
private ByteBuffer requestByteBuffer = null; //存放HTTP请求的缓冲区
private boolean requestReceived = false; //表示是否已经接收到HTTP请求的所有数据
private Request request = null; //表示HTTP请求
private Response response = null; //表示HTTP响应
RequestHandler(ChannelIO channelIO) {
this.channelIO = channelIO;
}
/* 接收HTTP请求,如果已经接收到了HTTP请求的所有数据,就返回true,否则返回false */
private boolean receive(SelectionKey sk) throws IOException {
ByteBuffer tmp = null;
if (requestReceived)return true; //如果已经接收到HTTP请求的所有数据,就返回true
//如果已经读到通道的末尾,或者已经读到HTTP请求数据的末尾标志,就返回true
if ((channelIO.read() < 0) || Request.isComplete(channelIO.getReadBuf())) {
requestByteBuffer = channelIO.getReadBuf();
return (requestReceived = true);
}
return false;
}
|