本篇介绍一个 I/O 技术的典型应用——远程传输文件,本实战采用的是CS架构。当客户端成功连接服务端后,服务端立即向客户端发送一个文件。
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();
}
}
}
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();
}
}
}
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 技术。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://blog.csdn.net/chengqiuming/article/details/124775635
内容来源于网络,如有侵权,请联系作者删除!