Java使用NioSocket手动实现HTTP服务器

  

<强> NioSocket简单复习

  

<强>重要概念

  

NioSocket里面的三个重要概念:缓冲区,频道,选择

  
      <李>缓冲区为要传输的数据李   <李>频道为传输数据的通道李   <李>选择器为通道的分配调度者李   
  

<强>使用步骤

  

使用NioSocket实现通信大概如以下步骤:

  
      <李> ServerSocketChannel可以通过configureBlocking方法来设置是否采用阻塞模式,设置为假后就可以调用寄存器注册选择器、阻塞模式下不可以用选择器。   <李>注册后,选择器就可以通过选择()来等待请求,通过参数设置等待时长,若传入参数0或者不传入参数,将会采用阻塞模式直到有请求出现。   <李>接收到请求后选择器调用selectedKeys方法,返回SelectedKey集合。   <李> SelectedKey保存了处理当前请求的渠道和选择器,并提供了不同的操作类型。四种操作属性:SelectedKey.OP_ACCEPT, SelectedKey.OP_CONNECT, SelectedKey.OP_READ SelectedKey.OP_WRITE。   <李>通过SelectedKey的千万,isConnectable, isReadable和isWritable来判断操作类型,并处理相应操作。   <李>在相应的处理程序中提取SelectedKey中的通道和缓冲信息并执行相应操作。
      李   
  

<>强实现HTTP

  

<>强创建HttpServer类作为程序的主要入口

        公开课HttpServer {   公共静态void main (String [] args){抛出异常   ServerSocketChannel ServerSocketChannel=ServerSocketChannel.open ();   serverSocketChannel.socket ()。绑定(新的InetSocketAddress ((8080)));   serverSocketChannel.configureBlocking(假);      选择器选择器=Selector.open ();//必须接受,否则就会抛出异常   serverSocketChannel。注册(选择器,SelectionKey.OP_ACCEPT);      而(真){   如果(selector.select (3000)==0) {   继续;   }      Iterator.iterator keyIter=selector.selectedKeys () ();      而(keyIter.hasNext ()) {   SelectionKey关键=keyIter.next ();   新线程(新HttpHandler(关键)).run ();   keyIter.remove ();   }   }   }   }      之前      

以上代码的逻辑大致遵循着NioSocket的大概用法,其中serverSocketChannel使用注册方法注册到选择器仅是OP_ACCEPT,使用其他操作就会操作。但是并不是说不能进行其他操作,而是其他操作稍后实现。

  

在serverSocketChannel.configureBlocking(假)后,非阻塞模式启动.Server接收到请求后就会将记录了请求信息的钥匙交给HttpHandler做详细处理,处理完就把钥匙从迭代器里面删除掉。可以看到出来,HttpServer对请求里面的信息一概不知,这样才能成为一个出色的管理层,它管理着HttpHandler来处理请求。

  

既然选用了NioSocket这样的新的IO, HttpHandler必然是多线程的实现(否则还有什么意义)。

  

<>强创建HttpHandler来处理请求

  

对于来自HttpServer的不加工信息,HttpHandler必须要做全套,因此需要HttpHandler自己考虑好有没有中文乱码,缓冲大小是多少等等.HttpHandler大概框架如下即可:

        类HttpHandler实现Runnable {   私人int bufferSize=1024;   私人字符串localCharset=皍tf - 8”;   私人SelectionKey关键;      公共HttpHandler (SelectionKey键){   这一点。键=键;   }      公共空间handleAccept()抛出IOException {}      公共空间handleRead()抛出IOException {}      @Override   公共空间run () {   尝试{   如果(key.isAcceptable ()) {   handleAccept ();   }   如果(key.isReadable ()) {   handleRead ();   }   }捕捉(IOException ex) {   ex.printStackTrace ();   }   }   }   之前      

如上框架简单明了,重载运行实现多线程,handleAccept和handleRead用于详细地处理相关操作,bufferSize规定缓冲大小,localCharset的设定提前防止中文乱码。

  

需要注意的是HttpServer里面,我们只注册了OP_ACCEPT这个操作,那么在HttpHandler里面只有千万要()判定为真,那么handleRead()怎么办呢?我们会在handleAccept()注册好的:

        公共空间handleAccept()抛出IOException {   SocketChannel clientChannel=((ServerSocketChannel) key.channel ()) .accept ();   clientChannel.configureBlocking(假);   clientChannel.register (   SelectionKey key.selector ()。OP_READ ByteBuffer.allocate (bufferSize)   );   }      

Java使用NioSocket手动实现HTTP服务器