e.printStackTrace();
try{
if(key!=null){
key.cancel();
key.channel().close();
}
}catch(Exception ex){e.printStackTrace();}
}
}//#while
}//#while
}
public static void main(String args[])throws Exception{
final HttpServer server = new HttpServer();
server.service();
}
}
在HttpServer类的service()方法中,当ServerSocketChannel向Selector注册接收连接就绪事件时,设置了一个AcceptHandler附件:
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT,new AcceptHandler());
AcceptHandler类的handle()方法负责处理接收连结就绪事件。当某种事件发生时,HttpServer类的service()方法从SelectionKey中获得Handler附件,然后调用它的handle()方法:
final Handler handler = (Handler)key.attachment();
handler.handle(key); //处理相关事件
2.具有自动增长的缓冲区的ChannelIO类
ChannelIO对SocketChannel进行了包装,增加了自动增长缓冲区容量的功能。当调用socketChannel.read(ByteBuffer buffer)方法时,如果buffer已满(即position=limit),那么即使通道中还有未接收的数据,read方法也不会读取任何数据,而是直接返回0,表示读到了零个字节。
为了能读取通道中的所有数据,必须保证缓冲区的容量足够大。在ChannelIO类中,有一个requestBuffer变量,它用来存放客户的HTTP请求数据,当requestBuffer剩余容量已经不足5%,并且还有HTTP请求数据未接收,ChannelIO会自动扩充requestBuffer的容量,该功能由resizeRequestBuffer()方法完成。
例程3是ChannelIO类的源程序,它的read()和write()方法利用SocketChannel来接收和发送数据,并且它还提供了实用方法transferTo(),该方法能把文件中的数据发送到SocketChannel中。
//例程3 ChannelIO.java
//此处省略import语句
public class ChannelIO {
protected SocketChannel socketChannel;
protected ByteBuffer requestBuffer; //存放请求数据
private static int requestBufferSize = 4096;
public ChannelIO(SocketChannel socketChannel, boolean blocking)
throws IOException {
this.socketChannel = socketChannel;
socketChannel.configureBlocking(blocking); //设置模式
requestBuffer = ByteBuffer.allocate(requestBufferSize);
}
public SocketChannel getSocketChannel() {
return socketChannel;
}
|