I/O应用实战——远程传输文件

x33g5p2x  于2022-05-16 转载在 其他  
字(2.4k)|赞(0)|评价(0)|浏览(221)

一 点睛

本篇介绍一个 I/O 技术的典型应用——远程传输文件,本实战采用的是CS架构。当客户端成功连接服务端后,服务端立即向客户端发送一个文件。

二 实战

1 服务端 

package io;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * @className: MyServer
 * @description: 服务端
 * @date: 2022/5/14
 * @author: cakin
 */
public class MyServer {
    public static void main(String[] args) throws IOException {
        // 服务的地址: 本机ip:8888
        ServerSocket server = new ServerSocket(8888);
        // 允许接收多个客户端连接
        while (true) {
            // 一直阻塞,直到有客户端发来连接
            Socket socket = server.accept();
            // 创建一个线程,用于给该客户端发送一个文件
            new Thread(new SendFile(socket)).start();
        }
    }
}

2 服务端向客户端发送文件

package io;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

// 服务端向客户端发送文件
public class SendFile implements Runnable {
    private Socket socket;

    public SendFile(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            System.out.println("连接成功!");
            OutputStream out = socket.getOutputStream();
            File file = new File("d:\\expJob.docx");
            InputStream fileIn = new FileInputStream(file);
            byte[] bs = new byte[64];
            int len = -1;
            while ((len = fileIn.read(bs)) != -1) {
                out.write(bs, 0, len);
            }
            fileIn.close();
            out.close();
            socket.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3 客户端

package io;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;

/**
 * @className: MyClient
 * @description: 客户端
 * @date: 2022/5/14
 * @author: cakin
 */
public class MyClient {
    public static void main(String[] args) throws UnknownHostException, IOException {
        // 客户端连接服务端发布的服务
        Socket socket = new Socket("127.0.0.1", 8888);
        // 接受服务端发来到文件
        InputStream in = socket.getInputStream();
        byte[] bs = new byte[64];
        int len = -1;
        OutputStream fileOut = new FileOutputStream("e:\\expJob.docx");
        while ((len = in.read(bs)) != -1) {
            fileOut.write(bs, 0, len);
        }
        System.out.println("文件接收成功!");
        fileOut.close();
        in.close();
        socket.close();
    }
}

三 测试

文件接收成功!

四 说明

先启动服务端,再启动客户端。服务端就会向客户端发送一个文件。

以上程序包含了使用 I/O 的基本步骤

1 将硬盘文件读入内存,使用输入流(InputStream 或 Reader)

2 将内存中的文件输出到硬盘,使用输出流(OutputStream 或 Writer)

3 将内存中的文件,远程发送给另一个计算机,使用 socket.getOutputStream()

4 接收远程发来的文件,并保存到本机内存中,使用 socket.getInputStream()

以上这种 I/O 实现相对简单,但性能较低,存在以下一些缺点。

1)数据以阻塞的方式传输。例如,服务端在接收客户端连接时,使用的是 server.accept(),而此方法会一直阻塞,直到客户端发来连接。也就是说,服务端在阻塞期间会一直等待,而不会再做其他任何事情。

2)当服务端每次收到新客户端发来的连接时,都会通过 new Thread(new SendFile(socket)).start() 创建一个新的线程,去处理这个客户端连接。而每次 JVM 创建一个线程,大约会消耗 1 MB 内存,并且在创建线程时 CPU 也会因为对线程上下文切换而消耗性能。因此,如果有大量的客户端发来连接,服务端的性能就会严重消耗。当高于某个阈值时,如果再继续增加线程,性能会不增反减。

正是因为 I/O 存在这些缺点,后续才衍生出 NIO 和 AIO 等新型 I/O  技术。

相关文章