1、案例分析
1.1、发送数据
1、【客户端】输入流,从硬盘读取文件数据到程序中。
2、【客户端】输出流,写出文件数据到服务端。
3、【服务端】输入流,读取文件数据到服务端程序。
4、【服务端】输出流,写出文件数据到服务器硬盘中。
1.2、信息回执
前四步与基本文件上传一致。
1、【服务端】获取输出流,回写数据。
2、【客户端】获取输入流,解析回写数据。
2、代码实现
客户端
public class ClientDemo {
public static void main(String[] args) throws IOException {
//创建字节缓冲输入流获取本地文件
BufferedInputStream br=new BufferedInputStream(new FileInputStream("F:\\1.jpg"));
//获取当前IP
String hostAddress = InetAddress.getLocalHost().getHostAddress();
//创建输出流 写到服务器端
Socket s=new Socket(hostAddress,10086);
OutputStream out = s.getOutputStream();
BufferedOutputStream bw=new BufferedOutputStream(out);
//写出数据
byte[] bytes=new byte[1024*8];
int len;
//读数据
while((len =br.read(bytes))!=-1){
//写数据
bw.write(bytes,0,len);
bw.flush();
}
//告诉服务端停止写操作
s.shutdownOutput();
//读取服务端回执信息
InputStream inputStream = s.getInputStream();
int read = inputStream.read(bytes);
System.out.println(new String(bytes,0,read));
//释放资源
bw.close();
br.close();
s.close();
}
}
服务端
public class ServiceDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10086);
//接收数据
Socket accept = ss.accept();
//调用获取输入流对象
InputStream inputStream = accept.getInputStream();
//使用高效缓冲流读取数据
BufferedInputStream bi = new BufferedInputStream(inputStream);
//创建缓冲输出流 为了让文件名不会重复,这里用毫秒值表示
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(System.currentTimeMillis() + ".jpg"));
byte[] bytes = new byte[1024 * 8];
int len;
while ((len = bi.read(bytes)) != -1) {
bo.write(bytes, 0, len);
}
OutputStream out = accept.getOutputStream();
out.write("文件已保存在服务端".getBytes());
//释放资源
bo.close();
bi.close();
System.out.println("文件上传已保存");
}
}
3、优化改进代码
1、服务端只保存一个文件就关闭了,之后的用户无法再上传,这是不符合实际的,使用循环和多线程改进,可以不断的接收不同用户的文件。
2、服务端在接收大文件时,可能耗费几秒钟的时间,此时不能接收其他用户上传,所以,使用多线程技术优化
客户端不用改变,这里只用修改服务端代码并添加一个线程类。
服务端
public class ServiceDemo {
public static void main(String[] args) throws IOException {
ServerSocket ss = new ServerSocket(10086);
while (true) {
//接收数据
Socket accept = ss.accept();
//使用线程 传递接口实现类对象 并把accept传递过去
new Thread(new ThreadDemo(accept)).start();
}
}
}
Runnable实现类
public class ThreadDemo implements Runnable{
//声明Socket对象
private Socket accept;
//有参构造,传递Socket对象
public ThreadDemo(Socket accept) {
this.accept = accept;
}
@Override
public void run() {
try{
InputStream inputStream = accept.getInputStream();
//使用高效缓冲流读取数据
BufferedInputStream bi = new BufferedInputStream(inputStream);
//创建缓冲输出流
BufferedOutputStream bo = new BufferedOutputStream(new FileOutputStream(System.currentTimeMillis() + ".jpg"));
byte[] bytes = new byte[1024 * 8];
int len;
while ((len = bi.read(bytes)) != -1) {
bo.write(bytes, 0, len);
}
OutputStream out = accept.getOutputStream();
out.write("文件已保存在服务端".getBytes());
//释放资源
bo.close();
bi.close();
System.out.println("文件上传已保存");
}catch (IOException e){
e.printStackTrace();
}
}
}