一个简单的Java NIO服务器

NIO 是 Java 1.4 引入的 java.nio 包,提供了 Channel、Selector、Buffer 等新的抽象,可以构建多路复用的、同步非阻塞 IO 程序,同时提供了更接近操作系统底层高性能的数据操作方式。

一般在Java中涉及高性能服务器编程时,会时候Netty等网络库,Netty的底层就是依赖于Java提供NIO机制。熟悉NIO编程对于理解Netty等网络库有很大的帮助。

下面代码展示了简单的Java NIO编程流程。

        服务器:NioServer

package com.nio;

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

public class NioServer {
    public static void main(String[] args) {

    	try{
    	    //得到一个Selecor对象(多路复用器)
            Selector selector = Selector.open();

            //Windows下: sun.nio.ch.WindowsSelectorImpl
            //Linux下:   sun.nio.ch.EPollSelectorImpl
            System.out.println(selector.getClass());
            
    	    //创建ServerSocketChannel,类似于BIO中的ServerSocket
            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();   

            //绑定端口9090
            serverSocketChannel.bind(new InetSocketAddress(9090));
            //设置为非阻塞
            serverSocketChannel.configureBlocking(false);

            //将serverSocketChannel注册到selector上,关注OP_ACCEPT
            serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

            //循环等待客户端连接
            while (true) {

                selector.select();

                //返回selector得到的结果集
                Set<SelectionKey> selectionKeys = selector.selectedKeys();

                //遍历 Set<SelectionKey>, 使用迭代器遍历
                Iterator<SelectionKey> keyIterator = selectionKeys.iterator();

                while (keyIterator.hasNext()) {
                    //获取到SelectionKey
                    SelectionKey selectionKey = keyIterator.next();
                    //根据key 对应的channel发生的事件做相应处理
                    if(selectionKey.isValid()){
                    	 //OP_ACCEPT, 有新的客户端连接
                        if(selectionKey.isAcceptable()) {
                        	
                            //客户端生成SocketChannel
                            SocketChannel socketChannel = serverSocketChannel.accept();

                            //SocketChannel 设置为非阻塞
                            socketChannel.configureBlocking(false);
                            
                            //将socketChannel 注册到selector, 关注OP_READ,同时给socketChannel关联一个Buffer
                            socketChannel.register(selector, SelectionKey.OP_READ, ByteBuffer.allocate(1024));
                        }
                        //OP_READ,有数据可以读
                        if(selectionKey.isReadable()) {  

                            //通过selectionKey获取到对应channel
                            SocketChannel channel = (SocketChannel)selectionKey.channel();

                            //获取到该channel关联的buffer
                            ByteBuffer buffer = (ByteBuffer)selectionKey.attachment();
                            channel.read(buffer);
                            System.out.println("form Client:" + new String(buffer.array()).trim());

                        }
                    }
                    //从集合中移动当前的selectionKey
                    keyIterator.remove();
                }
            }
    	}catch(IOException e){
    		e.printStackTrace();
    	}  
    }
}

客户端:NioClient

package com.nio;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

public class NioClient {
    public static void main(String[] args) {
        try{
            //得到一个SocketChannel
            SocketChannel socketChannel = SocketChannel.open();
            //设置非阻塞
            socketChannel.configureBlocking(false);
            //提供服务器端的ip和端口
            InetSocketAddress inetSocketAddress = new InetSocketAddress("127.0.0.1", 9090);
            
            //连接服务器,非阻塞情况下,需要调用finishConnect
            /*
             * If this channel is in non-blocking mode then an invocation of this method initiates 
             * a non-blocking connection operation. If the connectionis established immediately, 
             * as can happen with a local connection, then this method returns true. 
             * Otherwise this method returns false and the connection operation must 
             * later be completed by invoking the finishConnect method. 
             * 
             * */
            if(!socketChannel.connect(inetSocketAddress)){
            	while(!socketChannel.finishConnect()){
            		System.out.println("connect...");
            	}
            }
            	

            //如果连接成功,就发送数据
            String str = "hello, world";
            ByteBuffer buffer = ByteBuffer.allocate(str.length());
            buffer.put(str.getBytes());
            buffer.flip();
            
            //将数据写入 channel
            socketChannel.write(buffer);
            System.in.read();
	    }catch(IOException e){
		e.printStackTrace();
	    } 
    }
}

以上代码参考韩顺平老师的Netty课程中的NIO讲解部分。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值