课题分析:客户端读取本地硬盘文件,把文件传给服务器,服务器再把上传的文件保存到服务器的硬盘上。
实现步骤分析:
1.客户端使用本地字节输入流,读取本地硬盘上的问件;
2.客户端使用网络字节输出流,把读取的文件上传到服务器;
3.服务器端使用网络字节输入流,读取客户端上传的文件
4.服务器端使用本地字节输出流,将客户端的文件保存至服务器硬盘
5.服务器端使用网络字节输出流,向客户端传递"上传成功"信息
6.客户端使用网络字节输入流,收到来自服务器端的回信
7.释放资源
具体实现:
客户端实现:
具体实现步骤:
1.创建一个本地字节输入流FileInputStream对象,构造方法中绑定要读取的资源
2.创建一个客户端对象Socket,构造方法绑定服务器的IP地址以及端口号
3.使用Socket对象的getOutputStream()获取网络字节输出流OutputStream对象
4.使用本地字节输入流FileInputStream对象中的read(),读取本地文件
5.使用OutputStream对象的write(),给服务器发送数据
6.使用Socket对象的getInputStream() 获取网络字节输入流InputStream对象
7.使用InputStream对象的read(),读取服务器回写的数据
8.释放资源(FileInputStream Socket)
package com.socket.filesocket; import java.io.*; import java.net.Socket; public class Client { public static void main(String[] args) { try { //1.创建一个本地字节输入流FileInputStream对象,构造方法中绑定要读取的资源 FileInputStream fis= new FileInputStream("d:\1.jpg"); //2.创建一个客户端对象Socket,构造方法绑定服务器的IP地址以及端口号 Socket client=new Socket("127.0.0.1",8888); //3.使用Socket对象的getOutputStream()获取网络字节输出流OutputStream对象 OutputStream os= client.getOutputStream(); //4.使用本地字节输入流FileInputStream对象中的read(),读取本地文件 int len=0; byte[] bytes=new byte[1024]; while((len=fis.read(bytes))!=-1){ //5.使用OutputStream对象的write(),给服务器发送数据 os.write(bytes,0,len); } System.out.println("文件以传送"); client.shutdownOutput(); //6.使用Socket对象的getInputStream() 获取网络字节输入流InputStream对象 InputStream is= client.getInputStream(); //7.使用InputStream对象的read(),读取服务器回写的数据 while((len=is.read(bytes))!=-1){ //5.使用OutputStream对象的write(),给服务器发送数据 System.out.println(new String(bytes,0,len)); } //8.释放资源(FileInputStream Socket) fis.close(); client.close(); } catch (IOException e) { e.printStackTrace(); } } }
服务器端实现:
具体实现步骤:
1.创建服务器ServerSocket对象和系统要指定的端口号
2.使用ServerSocket的accept(),获取到请求的客户端对象Socket
3.使用Socket对象的getInputStream() 获取网络字节输入流InputStream对象
4.判断d:\iotest文件夹是否存在,不存在的话就创建一个
5.创建一个本地字节输出流FileOutputStream,构造方法中绑定要输出的目的地
6.使用InputStream对象的read(),读取客户端发送的的数据
7.使用本地数据输出流FileOutputStream对象的write(),把读取的文件保存到服务器的硬盘上
8.使用Socket对象的getOutputStream()获取网络字节输出流OutputStream对象
9.使用OutputStream对象的write(),给服务器发送"上传成功"
10.释放资源(Socket FileOutputStream ServerSocket)
注:以下代码为服务器端优化过代码
优化说明:1.对服务器保存至硬盘的图片名称进行了优化,修改为了:域名+毫秒值+随机数
2.将服务器进行了长时间监听,服务器的socket未关闭
3.为了提高多次上传的效率,将图片保存的步骤放入了多线程
package com.socket.filesocket; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.Random; public class Server { public static void main(String[] args) throws IOException { //1.创建服务器ServerSocket对象和系统要指定的端口号 ServerSocket serverSocket=new ServerSocket(8888); System.out.println("服务器端开启。。。请打开客户端连接"); //2.使用ServerSocket的accept(),获取到请求的客户端对象Socket /* 优化:让服务器一直处于监听状态(使accept死循环) 有一个客户端上传文件,就保存一个 */ while (true){ Socket server=serverSocket.accept(); /* 优化:当多台客户端去上传文件时,服务器的效率会降低 采用多线程,提高效率 一个客户端,开启一个线程 */ new Thread(new Runnable() { @Override public void run() { try { //3.使用Socket对象的getInputStream() 获取网络字节输入流InputStream对象 InputStream is=server.getInputStream(); //4.判断d:\iotest文件夹是否存在,不存在的话就创建一个 File file=new File("d:\iotest"); if(!file.exists()){ file.mkdirs(); } /* 自定义文件名,防止文件名相同形成覆盖 规则:域名+毫秒值+随机数 */ String filename="itcast"+System.currentTimeMillis()+new Random().nextInt(999999)+".jpg"; //5.创建一个本地字节输出流FileOutputStream,构造方法中绑定要输出的目的地 FileOutputStream fos=new FileOutputStream(file+"\"+filename); //6.使用InputStream对象的read(),读取客户端发送的的数据 int len=0; byte[] bytes=new byte[1024]; while((len=is.read(bytes))!=-1){ //7.使用本地数据输出流FileOutputStream对象的write(),把读取的文件保存到服务器的硬盘上 fos.write(bytes,0,len); } //8.使用Socket对象的getOutputStream()获取网络字节输出流OutputStream对象 //9.使用OutputStream对象的write(),给服务器发送"上传成功" server.getOutputStream().write("上传成功".getBytes()); //10.释放资源(Socket FileOutputStream ServerSocket) fos.close(); server.close(); }catch(IOException e){ e.printStackTrace(); } } }).start(); } } }