BIO、NIO区别总结

BIO、NIO区别总结

BIO方式是java1.4之前支持的传统socket编程方式,socket.accept()会阻塞。在任何时间点,只有一个客户端能占用数据通道。如客户端有数据延迟,通道出现阻塞。

NIO:监听注册事件,客户端连接转换为事件,供服务端处理。

 

对于如下情况,BIO、NIO表现。

 

等待数据时间

服务端处理数据时间

Request1

10s

1s

Request2

1s

2s

 

  1. 多线程处理请求

BIO等待时间=10+1+2=13s

NIO等待时间=1+2+7+1=11s

  1. 单线程处理请求

BIO等待时间=10+1+1+2=14s

NIO等待时间=1+2+7+1=11s

 

BIO、NIO模拟http

  1. BIOServer

package tomcat;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Date;

public class BioTomcat {
   
public static void sendResponse(Socket socket) throws IOException {
       
OutputStream outputStream = socket.getOutputStream();
       
BufferedWriter out = new BufferedWriter(new OutputStreamWriter(outputStream));
       
String show = "<html><h1 style='color: green'> BIOServer!!!" + new Date().getSeconds() + "</h1>" +
               
"今天是20181213日 星期四" +
               
"<html>" ;
       
out.write("HTTP/1.0 200 OK");
       
out.newLine();
       
//返回一个首部
       
out.write("Content-Type:text/html");
       
out.newLine();
        
out.write("Content-Length: " + show.length() );
       
out.newLine();
       
out.write("charset=gbk");
       
out.newLine();
       
// 根据 HTTP 协议, 空行将结束头信息
       
out.newLine();
       
// 输出请求资源
       
out.write(show);
       
out.newLine();
        
out.flush();
       
out.close();

    }

   
public static void main(String[] args) throws IOException {
       
ServerSocket server = new ServerSocket(8088);
       
System.out.println("服务器启动:8088");
       
while (true){
           
Socket socket = server.accept();
           
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
           
String line = null;
           
while ((line = reader.readLine()) != null && !line.isEmpty()){
               
System.out.println(line);
            }
           
sendResponse(socket);
           
socket.close();
        }
    }
}

  1. NIOServer
package tomcat;

import java.io.*;

import java.net.InetSocketAddress;

import java.nio.ByteBuffer;

import java.nio.CharBuffer;

import java.nio.channels.SelectionKey;

import java.nio.channels.Selector;

import java.nio.channels.ServerSocketChannel;

import java.nio.channels.SocketChannel;

import java.nio.charset.Charset;

import java.nio.charset.CharsetDecoder;

import java.util.Date;

import java.util.Iterator;

import java.util.Set;

public class NioTomcat {

    public static String getString(ByteBuffer buffer) {

        Charset charset = null;

        CharsetDecoder decoder = null;

        CharBuffer charBuffer = null;

        try

        {

            charset = Charset.forName("UTF-8");

            decoder = charset.newDecoder();

            charBuffer = decoder.decode(buffer.asReadOnlyBuffer());

            return charBuffer.toString();

        }

        catch (Exception ex)

        {

            ex.printStackTrace();

            return "";

        }

    }

    private static void listen(Selector selector) throws IOException {

        while (true){

            int wait = selector.select(1000);

            if (wait == 0){

                continue;

            }

            Set<SelectionKey> keys = selector.selectedKeys();

            Iterator<SelectionKey> iterator = keys.iterator();

            while (iterator.hasNext()){

                SelectionKey key = iterator.next();

                handle(key, selector);

                iterator.remove();

            }

        }

    }

    public static void handle(SelectionKey key, Selector selector) throws IOException {

        if (key.isAcceptable()){

            ServerSocketChannel server = (ServerSocketChannel)key.channel();

            server.accept().configureBlocking(false).register(selector, SelectionKey.OP_READ);

        } else if (key.isReadable()){

            SocketChannel socketChannel = (SocketChannel) key.channel();

            ByteBuffer buffer = ByteBuffer.allocate(1024);

            socketChannel.read(buffer);

            buffer.flip();

            System.out.println(getString(buffer));

            socketChannel.register(selector, SelectionKey.OP_WRITE);

        } else if (key.isWritable()){

            SocketChannel socketChannel = (SocketChannel) key.channel();

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(1024);

            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(byteArrayOutputStream));

            String show = "<html><h1 style='color: green'> NIOServer!!!" + new Date().getSeconds() + "</h1>" +

                    "今天是20181213日 星期四" +

                    "<html>" ;

            writer.write("HTTP/1.0 200 OK");

            writer.newLine();

            writer.write("Content-Type:text/html");

            writer.newLine();

            writer.write("Content-Length: " + show.length() );

            writer.newLine();

            writer.newLine();

            writer.write(show);

            writer.flush();

            writer.close();

            socketChannel.write(ByteBuffer.wrap(byteArrayOutputStream.toByteArray()));

            socketChannel.close();

        }

    }

    public static void main(String[] args) throws IOException {

        ServerSocketChannel server = ServerSocketChannel.open();

        server.bind(new InetSocketAddress(8000));

        server.configureBlocking(false);

        Selector selector = Selector.open();

        server.register(selector, SelectionKey.OP_ACCEPT);

        System.out.println("服务器启动8000");

        listen(selector);

    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值