使用 NIO 进行网络编程=>模拟 Http服务器

这篇文章只是为了 熟练使用 nio 写的个小 demo

原来的 bio 的在这里: https://blog.csdn.net/yali_aini/article/details/82598307

我就直接放代码了:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Base64;
import java.util.Date;
import java.util.Iterator;

public class SocketServer implements Runnable {

    // 多路复用选择器
    private Selector selector;

    private int capacity = 200;

    private String icon = "AAABAAEAQEAAAAEAIAAoQgAAFgAAACgAAABAAAAAgAAAAAEAIAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAD/6dn//+HM///48v///+nZ///Lpf//w5n//8OZ///Dmf//w5n//8OZ///Dmf//w5n//+HM///p2fjy///Ssv//tH///6Vl//+IM///iDP//4gz//+IM///iDP//4gz//+WTP//tH///+nZ4cz//5ZM//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+eWf//tH///8OZ///Dmf//w5n//8OZ///Dmf//rXL//55Z//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///rXL///jy0rL//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+eWf//+PL/0rL//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//61y8OX//48///+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///6dn//7R///+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//48Dmf//4czDmf//iDP//4gz//+IM///lkz//9Ky///48v+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//7R///+PP///iDP//4gz//+IM///iDP//4gz//+IM///iDP//7R48v//w5n//4gz//+IM///tHjyiDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+PP//hzP//iDP//4gz//+IM///iDP//4gz//+IM///iDP//7R//8OZ//+IM///jzjy/4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP///Dlw5n//4gz//+IM///iDP//4gz//+IM///iDP//4848v/48v//pWX//4gz//+IM///iDP//4gz///Dmf//iDP//6Vl///w5f//rXL//6Vl//+lZf//pWX//9Ky//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///hzP///8OZ//+IM///iDP//4gz//+IM///iDP//4gz//+8jP//pWX//4gz//+IM///iDP//4gz//+IM///w5n//4gz//+lZf//jz///4gz//+IM///iDP//4gz///Dmf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///4cz///+0f///iDP//4gz//+IM///iDP//4gz//+IM///2r//6dn//4gz//+IM///iDP//4gz//+IM///iDP//8OZ//+IM///pWX//4gz//+IM///iDP//4gz//+IM///w5n//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//+HMw5n//4gz//+IM///iDP//4gz//+IM///iDP//+HM//jy//+IM///iDP//4gz//+IM///iDP//4gz///Dmf//iDP//6Vl//+IM///iDP//4gz//+IM///iDP//8OZ//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///p2f///9Ky//+IM///iDP//4gz//+IM///iDP//4gz///hzP//iDP//4gz//+IM///iDP//4gz//+IM///w5n//4gz//+lZf//iDP//4gz//+IM///iDP//4gz///Dmf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+PP//48v//iDP//4gz//+IM///iDP//4gz//+IM///0rL//48///+IM///iDP//4gz//+IM///iDP//8OZ//+IM///pWX//4gz//+IM///iDP//4gz//+IM///w5n//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///vIz//7R///+IM///iDP//4gz//+IM///iDP//61y///Ssv//iDP//4gz//+IM///iDP//4gz///Dmf//iDP//6Vl//+IM///iDP//4gz//+IM///iDP//8OZ//+IM///iDP//4gz//+IM///iDP//4gz//+IM///jzjy///48v//jz///4gz//+IM///iDP//4gz//+IM///4cz//9q///+lZf//pWX//6Vl//+lZf//w5n//4gz//+lZf//iDP//4gz//+IM///iDP//4gz///Dmf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//9Ky/9q///+IM///iDP//4gz//+IM///iDP//48w5f///8OZ//+IM///pWX//4gz//+IM///iDP//4gz//+IM///w5n//4gz//+IM///iDP//4gz//+IM///iDP//9Ky0rL//4gz//+IM///iDP//4gz//+IM///jz///9qDmf//iDP//6Vl//+IM///iDP//4gz//+IM///iDP//8OZ//+IM///iDP//4gz//+IM///jz///+nZ///Ssv//iDP//4gz//+IM///iDP//4gz//+IM///nln//8OZ///Dmf//w5n//8OZ///Dmf//8OX/w5n//4gz//+PP///pWX//6Vl//+lZf//iDP//4gz//+IM///iDP//4gz//+WTP//pWX//6Vl//+lZf//iDP//4gz//+IM///nln///Dl/+nZ//+PP///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//+HM/8OZ//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///nln///jy+PL//55Z//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///hzP/Dmf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///rXL///jy///48v//tH///4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///4cz/w5n//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///tH+0f///iDP//4gz//+IM///iDP//4gz//+IM///iDP//+HM/8OZ//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///tH///9Ky//+tcv//pWX//6Vl//+lZf//pWX//8ul///48v///9Ky//+IM///iDP//4gz//+IM///iDP//4gz///Lpf//4cz//+HM//+0f///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///nln/+PL//55Z//+IM///iDP//4gz//+IM///iDP//4gz//+IM///jz///+nZy6X//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///nln///jy/55Z//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+WTP//+PL///+0f///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///jzjy/9q///+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//8ul///48v//vIz//4gz//+IM///iDP//4gz//+PP///vIz///jy/55Z//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//+nZ//+0f///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+eWf/48v//nln//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+eWf//+PLw5f//jz///4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//8OZpWX//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP/vIz//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//6Vl/8ul//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//6Vl/6Vl//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///48v//8OX//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///2r//tH///4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//55Z///48v+eWf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///4cz//7yM//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//61y//+0f///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//55Z///48v//nln//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//+HM//+eWf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+WTP///9q///+WTP//iDP//4gz//+IM///iDP//4gz//+IM///iDP//7yM///48v///6Vl//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///w5f//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//9qDmf//pWX//6Vl//+0f///y6X///jy//+lZf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gzvIz//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///pWX///+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM9q///+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//9Kylkz//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP/lkz//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//55Z/61y//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//55Z/+HM//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//55Z///48v/Ssv//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///Dmf/p2f//6dn/4cz//7R///+lZf//pWX//7RhzP//4cz//5ZM//+IM///iDP//4gz//+IM///iDP//7R48v//+PL//48///+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+PP///+PL//8OZ//+PP///iDP//4gz//+PP///w5n48v//pWX//4gz//+IM///iDP//4gz//+IM///iDP//61y///48v//6dn//+HM///hzP//4cz///jy///Dmf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///0rL//7R///+IM///iDP//4gz//+IM///iDP//4gz//+0f///rXL//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///nln///jy/55Z//+IM///iDP//4gz//+IM///iDP//4gz//+IM///tH///8OZ//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//8OZ4cz//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+8jP/48v//rXL//4gz//+IM///iDP//4gz//+WTP//2rDl//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///8OX//7R///+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP///Dl///w5f//0rL//8OZ///hzP/Lpf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//8ul//+lZf//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+0f///nln//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+eWf//jz///4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///hzP+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+WTP//iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///y6X/iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///pWX//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//8ul/4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//8ul//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///hzP+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz///48v//jz///4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+PP///pWX//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+lZf///8OZ//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///tH///8ul//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///y6X/nln//4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///jzjy///48v//jz///4gz//+IM///iDP//4gz//+IM///iDP//4gz//+IM///jzjy//jy//+eWf//iDP//4gz//+IM///iDP//4gz//+IM///jz///+nZ/8ul//+IM///iDP//4gz//+IM///iDP//4gz//+IM///iDP//9Ky+PL//6Vl//+IM///iDP//4gz//+IM///lkz//+nZtH///4gz//+IM///iDP//4gz//+IM///iDP//7R/2r///7R///+tcv//0rL///jy///av///nln//4gz//+IM///nln//9q/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";

    // 两个常量
    private static final String CRLF = "\r\n";
    private static final String BLANK = " ";

    public SocketServer(int port){
        try {
            // 1.打开多路复用选择器
            this.selector = Selector.open();
            // 2.打开服务器通道
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
            // 3.设置非阻塞
            serverSocketChannel.configureBlocking( false );
            // 4.绑定地址
            serverSocketChannel.bind(new InetSocketAddress(port));
            // 5.注册上去
            serverSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
            System.out.println("server start success...");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true){
            try {
                // 1.必须让 selectot 开始监听
                this.selector.select();
                // 2.获取多路选择器所有的结果集
                Iterator<SelectionKey> keyIterator = this.selector.selectedKeys().iterator();
                // 3.循环key
                while ( keyIterator.hasNext() ){
                    // 4.获取一个选择的元素
                    SelectionKey selectionKey = keyIterator.next();
                    // 5.删除这个元素
                    keyIterator.remove();
                    // 6.判断是否可用
                    if( selectionKey.isValid() ){
                        // 阻塞的时候
                        if( selectionKey.isAcceptable() ){
                            accept(selectionKey);
                        }
                        // 读取的时候
                        if( selectionKey.isReadable() ){
                            read(selectionKey);
                        }
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public void writeData(String in , SocketChannel socketChannel ){

        try{
            StringBuffer sb = new StringBuffer();
            // http 协议版本,状态码,描述
            sb.append("HTTP/1.1").append(BLANK).append(200).append(BLANK).append("love").append(CRLF);
            // 响应头
            sb.append("Server:Pkusoft Server/12.19.06.14").append(CRLF).append("Date:").append(new Date()).append(CRLF);

            String html = "";
            if( in.contains("favicon.ico") ){
                byte [] data = Base64.getDecoder().decode(icon);

                sb.append("Content-type:image/x-icon").append(CRLF);

                sb.append("Connection:keep-alive").append(CRLF);
                sb.append("Content-Length:").append( data.length ).append(CRLF).append(CRLF);

                socketChannel.write(ByteBuffer.wrap(sb.toString().getBytes()));
                socketChannel.write(ByteBuffer.wrap(data));
            }else{
                sb.append("Content-type:text/html").append(CRLF);
                html = "<meta charset='utf-8' /><h1>nio 牛批</h1>";
                sb.append("Connection:keep-alive").append(CRLF);
                // 正文长度:内容
                sb.append("Content-Length:").append( html.getBytes().length ).append(CRLF).append(CRLF);
                sb.append(html);
                socketChannel.write(ByteBuffer.wrap(sb.toString().getBytes()));
            }
        }catch (Exception e){
            e.printStackTrace();
        }

    }

    public void read(SelectionKey key){
        ByteBuffer buffer = ByteBuffer.allocate(capacity);

        SocketChannel socketChannel = (SocketChannel)key.channel();
        StringBuffer in = new StringBuffer();
        try {
            socketChannel.read(buffer);
            int len = -1;
            while ( socketChannel.isOpen() ){
                len = socketChannel.read(buffer);
                if( buffer.position()== 0 ){
                    break;
                }
                buffer.flip();
                in.append(new String(buffer.array() , "UTF-8"));
                System.out.println( new String(buffer.array() , "UTF-8") );
                buffer.clear();

            }

            writeData(in.toString() , socketChannel);

            System.out.println("write success...");
            key.channel().close();
            key.cancel();

        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    public void accept(SelectionKey key){
        if( key.channel() instanceof ServerSocketChannel ){
            try {
                // 获取服务通道
                ServerSocketChannel serverSocketChannel = (ServerSocketChannel)key.channel();
                // 执行阻塞方法
                SocketChannel socketChannel = serverSocketChannel.accept();
                // 设置非阻塞
                socketChannel.configureBlocking(false);
                // 注册到多路复用选择器上,并设置读取标识
                socketChannel.register(this.selector, SelectionKey.OP_READ);
                System.out.println("切换阻塞成功...");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }else{
            System.out.println("客服端阻塞了...");
        }
    }

    public static void main(String[] args) {
        new Thread( new SocketServer(8888) ).start();
    }

}

然后浏览器访问:127.0.0.1:8888

 

Client 代码:

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class Client {
    public static void main(String[] args) throws Exception {
        SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 8888));

        socketChannel.write(Charset.forName("utf-8").encode("你好..."));

        ByteBuffer buffer = ByteBuffer.allocate(1024);

        socketChannel.read(buffer);
        System.out.println(new String(buffer.array(), "UTF-8").trim());

    }
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值