<强> 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服务器