java 怎么实现http下的异步socket

2024-12-01 05:22:34
推荐回答(1个)
回答1:

package com.what21.httpserver.nio;
import java.net.InetSocketAddress;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class MyHttpServer {
    /**
     * 启动服务
     * 
     * @param port
     * @throws Exception
     */
    public static void startServer(int port)throws Exception {
        // 创建选择器
        Selector selector = Selector.open();
        // 打开监听信道
        ServerSocketChannel server = ServerSocketChannel.open();
        // 与本地端口绑定
        server.socket().bind(new InetSocketAddress(port));
        // 设置为非阻塞模式
        server.configureBlocking(false);
        // 非阻塞信道才能够注册选择器,在注册过程中指出该信道可以进行Accept操作
        SelectionKey serverkey = server.register(selector,SelectionKey.OP_ACCEPT);
        // 反复循环,等待IO
        while (true) {
            // 取到选择器的监听事件
            selector.select();
            // 取到通道内监听事件的集合
            Set keys = selector.selectedKeys();
            // 遍历监听事件
            for (Iterator it = keys.iterator(); it.hasNext();) {
                SelectionKey key = (SelectionKey) it.next();
                //移出此事件
                it.remove();
                if (key == serverkey) {
                    if (key.isAcceptable()) {
                        // 取到对应的SocketChannel
                        SocketChannel client = server.accept();
                        if (client == null){
                            continue;
                        }
                        client.configureBlocking(false);
                        // 在此通道上注册事件
                        client.register(selector,SelectionKey.OP_READ);
                    }
                } else {
                    // 处理{@link SelectionKey#OP_READ}事件
                    SocketChannel client = (SocketChannel) key.channel();
                    if (!key.isReadable()){
                        continue;
                    }
                    key.cancel(); 
                    new MyHandler(client).start();
                }
            }
        }
    }
    /**
     * @param args
     * @throws Exception
     */
    public static void main(String[] args) throws Exception {
        startServer(8000);
    }
}

package com.what21.httpserver.nio;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class MyHandler extends Thread {
    // 编码
    static CharsetEncoder encoder = Charset.forName("GBK").newEncoder();
    private SocketChannel client;
    public MyHandler(SocketChannel client){
        this.client = client;
    }
    @Override
    public void run() {
        try {
            //==============================请求处理开始==============================
            ByteBuffer buffer = ByteBuffer.allocate(1024);
            client.read(buffer);
            // 将缓冲区准备为数据传出状态
            buffer.flip();
            CharsetDecoder decoder =  Charset.forName("GBK").newDecoder();
            String rquestStr= decoder.decode(buffer).toString();
            System.out.println(rquestStr);
            //==============================响应处理开始==============================
            String html = "

HI~ , My HTTP Server!

";
            // 响应头
            StringBuilder sb = new StringBuilder();
            sb.append("HTTP/1.0 200 OK").append("\r\n");
            sb.append("MIME_version:1.0").append("\r\n");
            sb.append("Content_Type:text/html").append("\r\n");
            sb.append("Content_Length:" + html.length()).append("\r\n");
            sb.append("\r\n");
            // 响应内容
            sb.append(html).append("\r\n");
            sb.append("\r\n");
            buffer=ByteBuffer.wrap(sb.toString().getBytes());
            client.write(buffer);
        } catch (Exception e) {
            e.printStackTrace();
        } finally{
            try {
                client.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}