流程简单分析
- 【客户端】输入流,从硬盘读取文件数据到程序中。
- 【客户端】输出流,写出文件数据到服务端。
- 【服务端】输入流,读取文件数据到服务端程序。
- 【服务端】输出流,写出文件数据到服务器硬盘中。
客户端实现
public class C_Test_02 {
public static void main(String[] args) {
try {
Socket socket = new Socket(InetAddress.getLocalHost(),8888);
// 创建输入缓冲流,读取本地文件
BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream("E:\\aaa.txt"));
// 创建输出流,用于向服务端发送文件
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(socket.getOutputStream());
// 读取并写入数据
byte[] bytes = new byte[1024];
int len ;
while ((len = bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
bufferedOutputStream.flush();
}
// 关闭连接关闭输出输出流
socket.close();
bufferedOutputStream.close();
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
服务端实现
public class S_Test_02 {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8888);
Socket accept = serverSocket.accept();
// 创建输入流,用于接受客户端的文件
BufferedInputStream bufferedInputStream = new BufferedInputStream(accept.getInputStream());
// 创建输出流,将客户端的文件保存到本地
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("E:\\bbb.txt"));
// 读取并保存文件
byte[] bytes = new byte[1024];
int len ;
while ((len = bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
bufferedOutputStream.flush();
}
// 关闭连接,关闭输入输出流
serverSocket.close();
bufferedOutputStream.close();
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
优化分析
文件名称写死问题
使用系统时间对文件进行重命名,保证文件名称唯一,避免覆盖文件导致最终服务端硬盘只保留一个文件
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("E:\\"+System.currentTimeMillis()+".txt"));
循环接收问题
服务端接收一个文件就关闭了,之后用户便无法上传,这很不符合实际,使用循环进行改进,可以不断接收来自客户端的文件
// 每次接收新的连接,创建一个Socket
while(true){
ServerSocket serverSocket = new ServerSocket(8888);
Socket accept = serverSocket.accept();
......
}
效率问题
服务端,在接收大文件时,可能耗费几秒钟的时间,此时不能接收其他用户上传,所以,使用多线程技术优化,代码如下:
while(true){
ServerSocket serverSocket = new ServerSocket(8888);
Socket accept = serverSocket.accept();
// accept 交给子线程处理.
new Thread(() -> {
......
InputStream bis = accept.getInputStream();
......
}).start();
}
修改后的
public class S_Test_02 {
public static void main(String[] args) {
try {
while (true){
ServerSocket serverSocket = new ServerSocket(8888);
Socket accept = serverSocket.accept();
new Thread(()->{
try{
// 创建输入流,用于接受客户端的文件
BufferedInputStream bufferedInputStream = new BufferedInputStream(accept.getInputStream());
// 创建输出流,将客户端的文件保存到本地
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream("E:\\培训\\day0901\\"+System.currentTimeMillis()+".txt"));
// 读取并保存文件
byte[] bytes = new byte[1024];
int len ;
while ((len = bufferedInputStream.read(bytes))!=-1){
bufferedOutputStream.write(bytes,0,len);
bufferedOutputStream.flush();
}
// 关闭连接,关闭输入输出流
serverSocket.close();
bufferedOutputStream.close();
bufferedInputStream.close();
}catch (Exception e){
e.printStackTrace();
}
}).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}