NIO Server简单实现

Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。

Java NIO: Channels and Buffers(通道和缓冲区)

标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。

Java NIO: Non-blocking IO(非阻塞IO)

Java NIO可以让你非阻塞的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。

Java NIO: Selectors(选择器)

Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。

package com.xxx.xxxController;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
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 NioServer {
    private Selector selector;

    public void initServer(String adrress, int port) throws IOException {
        //1:建立一个Socket连接通道
        ServerSocketChannel nioSocketChannel = ServerSocketChannel.open();
        //2: 将连接设置成非阻塞
        nioSocketChannel.configureBlocking(false);
        //3: 绑定socket监听地址
        nioSocketChannel.socket().bind(new InetSocketAddress(adrress, port));
        //4: 获取通道管理器
        this.selector = Selector.open();
        //5: 将通道与管理器绑定, 并注册SelectionKey.OP_ACCEPT事件
        nioSocketChannel.register(this.selector, SelectionKey.OP_ACCEPT);
    }

    public void listen() throws IOException {
        System.out.println("server started");
        while (true) {
            //监听客户端事件,阻塞
            selector.select();
            Set<SelectionKey> keySet =  selector.selectedKeys();
            //处理客户端连接和请求
            Iterator<SelectionKey> it = keySet.iterator();
            while (it.hasNext()) {
                SelectionKey key = it.next();
                it.remove();
                handler(key);
            }
        }
    }

    public void handler(SelectionKey key) throws IOException {
        if(key.isAcceptable()) {
            handlerAccept(key);
        } else if(key.isReadable()) {
            handlerRead(key);
        }
    }

    public void handlerAccept(SelectionKey key) throws IOException {
        //获取Key上绑定的通道
        ServerSocketChannel nioSocketChannel = (ServerSocketChannel) key.channel();
        //监听连接并返回连接的通道,非阻塞通道直接返回
        SocketChannel acceptChannel = nioSocketChannel.accept();
        acceptChannel.configureBlocking(false);

        System.out.println("new client accepted");

        //将通道与管理器绑定, 并注册SelectionKey.OP_事件
        acceptChannel.register(this.selector, SelectionKey.OP_READ);
    }

    public void handlerRead(SelectionKey key) throws IOException {
        SocketChannel readChannel = (SocketChannel) key.channel();
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        int read =  readChannel.read(buffer);
        if(read > 0) {
            byte[] data = buffer.array();
            String msg = new String(data).trim();
            System.out.println("clent sent msg :" + msg);

            ByteBuffer outBuffer = ByteBuffer.wrap("msg confirmed!".getBytes());
            readChannel.write(outBuffer);
        } else {
            System.out.println("客户端关闭");
            key.cancel();
        }

    }

    public static void main(String[] args){
        NioServer nioServer = new NioServer();
        try {
            nioServer.initServer("127.0.0.1", 8888);
            nioServer.listen();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

 
使用telnet客户端  telnet 127.0.0.1 8888
    
    输出结果:
    server started
    new client accepted
    clent sent msg :s
    clent sent msg :d
    clent sent msg :m
    clent sent msg :q
    客户端关闭

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 C++ 中,可以使用 Boost.Asio 库来实现 NIO(New Input/Output)模型。Boost.Asio 提供了高效的异步网络编程和底层 I/O 操作支持,可以实现 TCP、UDP、SSL 等协议的数据传输。 下面是一个简单的 Boost.Asio TCP 客户端的实现示例: ```cpp #include <iostream> #include <boost/asio.hpp> using boost::asio::ip::tcp; int main() { try { boost::asio::io_context io_context; // 创建 TCP socket tcp::socket socket(io_context); // 连接服务器 tcp::resolver resolver(io_context); boost::asio::connect(socket, resolver.resolve("localhost", "daytime")); // 发送请求 std::string request = "Hello, server!"; boost::asio::write(socket, boost::asio::buffer(request)); // 接收响应 char response[1024]; boost::asio::read(socket, boost::asio::buffer(response, request.size())); // 输出响应 std::cout << "Response: " << response << std::endl; } catch (std::exception& e) { std::cerr << "Exception: " << e.what() << std::endl; } return 0; } ``` 在这个示例中,首先创建了一个 io_context 对象,它是 Boost.Asio 库的核心。然后创建了一个 TCP socket 对象,并使用 resolver 对象解析服务器地址。接着使用 connect 函数连接服务器,并使用 write 函数发送请求,使用 read 函数接收响应。最后输出响应字符串。 需要注意的是,上述示例中的所有 I/O 操作都是异步的,要使用回调函数来进行处理。例如,可以使用 async_read 函数来进行异步读取操作,然后在回调函数中处理读取到的数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值