package me.ztiany.nio;


import org.junit.Test;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

import static me.ztiany.nio.Utils.close;

/*
 * 一、使用 NIO 完成网络通信的三个核心：
 *
 * 1. 通道（Channel）：负责连接
 *
 * 	   java.nio.channels.Channel 接口：
 * 			|--SelectableChannel
 * 				|--SocketChannel
 * 				|--ServerSocketChannel
 * 				|--DatagramChannel
 *
 * 				|--Pipe.SinkChannel
 * 				|--Pipe.SourceChannel
 *
 * 2. 缓冲区（Buffer）：负责数据的存取
 *
 * 3. 选择器（Selector）：是 SelectableChannel 的多路复用器。用于监控 SelectableChannel 的 IO 状况
 *
 */
public class BlockingNIO {

    /*
    1529751188670 server close
    1529751188659 client close
     */

    //客户端
    @Test
    public void client() {
        //1. 获取通道
        try (SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9898));
             FileChannel inChannel = FileChannel.open(Paths.get("file/text.txt"), StandardOpenOption.READ)) {

            //2. 分配指定大小的缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);
            //3. 读取本地文件，并发送到服务端
            while (inChannel.read(buf) != -1) {
                buf.flip();
                sChannel.write(buf);
                buf.clear();
            }

        } catch (IOException e) {
            e.printStackTrace();
        }
        System.out.println(System.currentTimeMillis() + " clien close");
    }

    //服务端
    @Test
    public void server() {
        //1. 获取通道
        SocketChannel sChannel = null;
        FileChannel outChannel = null;
        try (ServerSocketChannel ssChannel = ServerSocketChannel.open()) {

            outChannel = FileChannel.open(Paths.get("file/text_copy.txt"), StandardOpenOption.WRITE, StandardOpenOption.CREATE);

            //2. 绑定连接
            ssChannel.bind(new InetSocketAddress(9898));
            //3. 获取客户端连接的通道
            sChannel = ssChannel.accept();
            //4. 分配指定大小的缓冲区
            ByteBuffer buf = ByteBuffer.allocate(1024);
            //5. 接收客户端的数据，并保存到本地
            while (sChannel.read(buf) != -1) {
                buf.flip();
                outChannel.write(buf);
                buf.clear();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            close(sChannel);
            close(outChannel);
        }
        System.out.println(System.currentTimeMillis() + " server close");
    }



}
