需求说明:
实现客户端向服务端上传文件的功能
当启动服务端后,运行客户端程序,系统提示客户在客户端输入上传文件的完整路径。当客户在客户端输入完成后,服务端实现文件上传
实现思路:
创建客户端类 FileClient 和服务端类 FileServer
在客户端类中定义uploadFile(Socket socket)方法,用于上传文件,使用BufferedOutputStream包装socket中输入流对象,使用new FileInputStream输入流对象读取本地文件,使用输出流将文件利用socket管道将数据循环发送至服务端
在客户端FileCliet类中,使用new Socket连接本地服务端和端口,调用uploadFile方法实现文件上传
在服务端类FileServer中,定义downFile()方法用于下载文件,该方法中使用BufferedInputStream包装socket中的输入流读取文件内容,并且使用FileOutputStream写到本地
分别运行服务端和客户端程序进行测试
实现代码:
服务端类 FileServer
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; public class FileServer { public ServerSocket server; public Socket socket; public void downloadFile() { BufferedInputStream bis = null; BufferedOutputStream bos = null; try { // 获取Socket管道字节输入流 InputStream in = socket.getInputStream(); // 将Socket管道字节输入流,进行缓冲包装提高读取的速度 bis = new BufferedInputStream(in); // 读取客户端发送的文件名 int length = bis.read(); byte[] b = new byte[length]; bis.read(b); // 获取需要下载的文件名 String fileName = this.getFileName(new String(b)); // 下载的文件对象 FileOutputStream fos = new FileOutputStream("H://" + this.getFileName(fileName)); // 对FileOutputStream进行缓冲包装,提高写入的速度 bos = new BufferedOutputStream(fos); // 创建临时变量保存数据 int data = 0; // 写入文件 while ((data = bis.read()) != -1) { bos.write(data); } System.out.println("客户/" + socket.getInetAddress() + ":上传文件[" + fileName + "]成功"); } catch (IOException e) { e.printStackTrace(); } finally { try { if (bis != null) { bis.close(); } if (bos != null) { bos.close(); } server.close(); } catch (IOException e) { e.printStackTrace(); } } } // 对文件的全路径进行拆分,返回文件名 private String getFileName(String fn) { String[] files = fn.split("/"); return files[files.length - 1]; } // 创建服务器 public void crateServer() { try { // 创建Socket实例 server = new ServerSocket(8888); // 创建while循环接受多个客户端的连接 while (true) { // 每一个连接的客户端都与服务器维护一条专属的Socket通信管道 socket = server.accept(); System.out.println("客户端已经连接"); downloadFile(); break; } } catch (IOException e) { e.printStackTrace(); } } public static void main(String[] args) { new FileServer().crateServer(); } }
客户端类 FileClient
import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.Socket; public class FileClient { // 向服务器发送数据 public void uploadFile(Socket socket) { BufferedReader reader = null; BufferedInputStream bis = null; BufferedOutputStream bos = null; try { System.out.println("请输入要上传文件的完成路径:"); // 接收键盘输入 InputStream in = System.in; // 获取Socket管道字节输出流 OutputStream out = socket.getOutputStream(); // 使用BufferedReader包装,便于按行读取客户端输入的数据 reader = new BufferedReader(new InputStreamReader(in)); // 客户端上传到服务端文件的名字 String fileName = reader.readLine(); // 创建字符文件输入流,用于读取上传文件中的数据 FileInputStream fis = new FileInputStream(fileName); // 使用字节输入缓冲提高读取的速度 bis = new BufferedInputStream(fis); // 获取Socket管道输出流,将从文件中的数据写入到管道中 bos = new BufferedOutputStream(out); byte[] nbt = fileName.getBytes(); // 将文件名字符串转换成字节数组的长度写入到Socket管道中 bos.write(nbt.length); // 将字节数组写入到Socket管道中 bos.write(nbt); // 定义临时变量,将从文件中读取到的数据写入到Socket管道中 int data = 0; // 将文件中的数据写入到Socket管道中 while ((data = bis.read()) != -1) { bos.write(data); } } catch (IOException e) { e.printStackTrace(); } finally { // 关闭io流和socket try { if (reader != null) { reader.close(); } if (bis != null) { bis.close(); } if (bos != null) { bos.close(); } socket.close(); } catch (IOException e) { e.printStackTrace(); } } } public static void main(String[] args) { Socket client = null; try { // 创建客户端套接字对象 client = new Socket("127.0.0.1", 8888); new FileClient().uploadFile(client); } catch (IOException e) { e.printStackTrace(); } } }