网络I/o编程模型9 传统io与Nio传输文件的区别

本文探讨了传统IO与NIO在Java中客户端与服务端的实现,包括使用FileInputStream/OutputStream与SocketChannel/FileChannel进行文件读写,并比较了两者在性能和操作上的差异。NIO通过`transferTo`和`ByteBuffer`展示了零拷贝的优势。

一 传统IO

1.1 传统IO的客户端

public class IOClient {
    public static void main(String[] args) throws IOException {
        Socket socket = new Socket("localhost", 7001);
        String fileName = "d:/test-file/P2PR203702_2021-06-29 09-33-26 186.txt";
        InputStream inputStream = new FileInputStream(fileName);
        DataOutputStream dataOutputStream = new DataOutputStream(socket.getOutputStream());
        byte[] buffer = new byte[4096];
        long readCount;
        long total = 0;

        long startTime = System.currentTimeMillis();

        while ((readCount = inputStream.read(buffer)) >= 0) {
            total += readCount;
            dataOutputStream.write(buffer);
        }

        System.out.println("发送总字节数: " + total + ", 耗时: " + (System.currentTimeMillis() - startTime));

        dataOutputStream.close();
        socket.close();
        inputStream.close();
    }
}

1.2 传统IO的服务端

public class IOServer {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = new ServerSocket(7001);

        while (true) {
            Socket socket = serverSocket.accept();
            DataInputStream dataInputStream = new DataInputStream(socket.getInputStream());

            try {
                byte[] byteArray = new byte[4096];

                while (true) {
                    int readCount = dataInputStream.read(byteArray, 0, byteArray.length);
                    System.out.println("readCount:"+readCount);

                    if (-1 == readCount) {
                        break;
                    }
                    String content=new String(byteArray,0,readCount);
                    System.out.println("content:"+content);
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
}

1.3 调试结果

二  Nio实现此功能

2.1  NIO客户端

public class NIOClient {
    public static void main(String[] args) throws IOException {
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.connect(new InetSocketAddress("localhost", 7002));
        String filename = "d:/test-file/P2PR203702_2021-06-29 09-33-26 186.txt";

        //得到一个文件channel
        FileChannel fileChannel = new FileInputStream(filename).getChannel();

        //准备发送
        long startTime = System.currentTimeMillis();

        //在linux下一个transferTo 方法就可以完成传输
        //在windows 下 一次调用 transferTo 只能发送8m , 就需要分段传输文件, 而且要主要
        //传输时的位置 =》 课后思考...
        //transferTo 底层使用到零拷贝
        long transferCount = fileChannel.transferTo(0, fileChannel.size(), socketChannel);

        System.out.println("发送的总的字节数 =" + transferCount + " 耗时:" + (System.currentTimeMillis() - startTime));

        //关闭
        fileChannel.close();
    }
}

2.2  NIO服务端

 输出内容:System.out.println("from 客户端:"+new String(byteBuffer.array()));

public class NIOServer {
    public static void main(String[] args) throws IOException {

            InetSocketAddress address = new InetSocketAddress(7002);

            ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

            ServerSocket serverSocket = serverSocketChannel.socket();

            serverSocket.bind(address);

            //创建buffer
            ByteBuffer byteBuffer = ByteBuffer.allocate(4096);

            while (true) {
                SocketChannel socketChannel = serverSocketChannel.accept();
                int readcount = 0;
                while (-1 != readcount) {
                    try {
                        readcount = socketChannel.read(byteBuffer);
                        System.out.println("from 客户端:"+new String(byteBuffer.array()));


                    }catch (Exception ex) {
                        // ex.printStackTrace();
                        break;
                    }
                    //
                    byteBuffer.rewind(); //倒带 position = 0 mark 作废
                }
            }
        }

}

2.3 结果

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值