Java NIO Buffer Channel Selector

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Dopamy_BusyMonkey/article/details/82668648

1、缓冲区类型:

ByteBuffer
CharBuffer
ShortBufer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer,并没有 BooleanBuffer

2、ByteBuffer 基本操作

import java.nio.ByteBuffer;

public class MainNioTest {

	public static void main(String[] args) {
		//初始化
		ByteBuffer buffer = ByteBuffer.allocate(10);
		//保存
		buffer.put("1234567".getBytes());
		//反转(读写转换)
		buffer.flip();
		//读取
		while (buffer.hasRemaining()) {
			System.out.print((char)buffer.get());
		}
	}
}

3、ByteBuffer 继承类

HeapByteBuffer 分配在jvm堆内存
DirectByteBuffer 直接分配在内存
DirectByteBufferR 返回只一个只读对象,无法写操作
MappedByteBuffer 大文件操作

4、Channel通道类型

FileChannel:从文件中读写数据
DatagramChannel:能通过UDP读写网络中的数据。
SocketChannel:能通过TCP读写网络中的数据。
ServerSocketChannel:可以监听新进来的TCP连接,像Web服务器那样。对每一个新进来的连接都会创建一个SocketChannel

5、Buffer和Channel

import java.io.File;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class MainNIoChannel {

	public static void main(String[] args) throws Exception {
		String path = "D:"+File.separator+"data.txt";

        RandomAccessFile aFile = new RandomAccessFile(path,"rw");
        FileChannel channel = aFile.getChannel();//得到管道
        //借助一个Buffer来与Channel进行交互
        ByteBuffer buffer = ByteBuffer.allocate(1025);
        int readByteLen;
        while((readByteLen = channel.read(buffer)) != -1){
            System.out.println("读取到buffer中的数据长度为:"+readByteLen);
            System.out.println("内容如下:");
            //将Buffer从写模式切换到读模式
            buffer.flip();
            while(buffer.hasRemaining()){
                System.out.print((char)buffer.get());
            }
            buffer.clear();

            System.out.println();//换行
        }
        aFile.close();
	}
}

6、Selector

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 MainSelectorServer {

	public static void main(String[] args) throws Exception {
		MainSelectorServer server = new MainSelectorServer();
        server.init(9999);
        server.listen();
	}

	// 通道选择器
	private Selector selector;

	public MainSelectorServer(){
        try {
            selector = Selector.open();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

	/*
	 * 函数功能:服务器端开始监听,看是否有客户端连接进来
	 */
	private void listen() throws Exception {
		System.out.println("server running....");
		while (true) {
			// 当注册事件到达时,方法返回,否则该方法会一直阻塞
			selector.select();
			// 获得selector中选中的相的迭代器,选中的相为注册的事件
			Set<SelectionKey> set = selector.selectedKeys();
			Iterator<SelectionKey> ite = set.iterator();
			while (ite.hasNext()) {
				SelectionKey selectionKey = (SelectionKey) ite.next();
				// 删除已选的key 以防重负处理
				ite.remove();
				if (selectionKey.isAcceptable()) {// 如果有客户端连接进来
					// 先拿到这个SelectionKey里面的ServerSocketChannel。
					ServerSocketChannel serverSocketChannel = (ServerSocketChannel) selectionKey.channel();
					SocketChannel socketChannel = serverSocketChannel.accept();
					System.out.println("有客户端连接到服务器!!!");
					socketChannel.configureBlocking(false);// 将此通道设置为非阻塞
					Thread.sleep(2000);
					socketChannel.write(ByteBuffer.wrap(new String("hello client!").getBytes()));
					socketChannel.register(selector, SelectionKey.OP_READ);
				} else if (selectionKey.isReadable()) {// 客户端发送数据过来了
					// 先拿到这个SelectionKey里面的SocketChannel。
					SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
					// 接收来自于客户端发送过来的数据
					ByteBuffer buf = ByteBuffer.allocate(13);
					while (socketChannel.read(buf) != -1) {
						byte[] receData = buf.array();
						String msg = new String(receData).trim();
						Thread.sleep(2000);
						System.out.println("接收来自客户端的数据为:" + msg);
						buf.clear();
					}
				}
			}
		}
	}

	/*
	 * 函数功能:初始化serverSocketChannel来监听指定的端口是否有新的TCP连接,
	 * 并将serverSocketChannel注册到selector中
	 */
	private void init(int port) {
		try {
			ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
			// serverSocketChannel监听指定端口
			serverSocketChannel.socket().bind(new InetSocketAddress(port));
			serverSocketChannel.configureBlocking(false);// 设置为非阻塞模式
			// 将serverSocketChannel注册到selector中,并为该通道注册selectionKey.OP_ACCEPT事件
			// 注册该事件后,当事件到达的时候,selector.select()会返回, 如果事件没有到达selector.select()会一直阻塞
			serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
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.SocketChannel;
import java.util.Iterator;
import java.util.Set;

public class MainSelectorClient {

	public static void main(String[] args) throws Exception {
		MainSelectorClient client = new MainSelectorClient();
		client.init("localhost", 9999);
		client.connect();
	}

	private Selector selector;

	public MainSelectorClient() throws IOException {
		this.selector = Selector.open();
	}

	private void init(String address, int port) throws IOException {
		// 客户端,首先有一个SocketChannel
		SocketChannel socketChannel = SocketChannel.open();
		socketChannel.configureBlocking(false);// 将此通道设置为非阻塞模式
		socketChannel.connect(new InetSocketAddress(address, port));
		// 将SocketChannel注册到selector中,并为该通道注册SelectionKey.OP_CONNECT
		socketChannel.register(selector, SelectionKey.OP_CONNECT);
	}

	private void connect() throws Exception {
		while (true) {
			selector.select();
			Set<SelectionKey> set = selector.selectedKeys();
			Iterator<SelectionKey> ite = set.iterator();
			while (ite.hasNext()) {
				SelectionKey selectionKey = (SelectionKey) ite.next();
				ite.remove(); // 删除已选的key,以防重复处理
				if (selectionKey.isConnectable()) {// 看是否有连接发生
					SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
					// 如果正在连接,则完成连接
					if (socketChannel.isConnectionPending()) {
						socketChannel.finishConnect();
					}
					socketChannel.configureBlocking(false);// 设置为非阻塞模式
					// 给服务器端发送数据
					System.out.println("客户端连接上了服务器端。。。。");
					Thread.sleep(2000);
					socketChannel.write(ByteBuffer.wrap(new String("hello server!").getBytes()));
					// 为了接收来自服务器端的数据,将此通道注册到选择器中
					socketChannel.register(selector, SelectionKey.OP_READ);
				} else if (selectionKey.isReadable()) {
					SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
					// 接收来自于服务器端发送过来的数据
					ByteBuffer buf = ByteBuffer.allocate(13);
					while (socketChannel.read(buf) != -1) {
						byte[] receData = buf.array();
						String msg = new String(receData).trim();
						Thread.sleep(2000);
						System.out.println("接收来自服务器端的数据为:" + msg);
						buf.clear();
					}
				}
			}
		}
	}
}

猜你喜欢

转载自blog.csdn.net/Dopamy_BusyMonkey/article/details/82668648