1.1 文件上传案例:
文件上传案例图解:
- 【客户端】输入流,从硬盘中读取文件数据到程序中。
- 【客户端】输出流,写出文件数据到服务端。
- 【服务端】输入流,读取文件数据到服务器程序。
- 【服务端】输出流,写出文件数据到服务器硬盘中。
1.客户端代码实现
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
/*
文件上传案例客户端代码实现:暂不考虑多线程版
思路:
1.根据服务器端IP地址和端口号创建客户端Socket对象
2.关闭Socket
3.创建字节输入流关联目标文件:要上传的文件
4.获得字节输出流对象
5.定义字节数组存储读取到的文件数据
6.定义整型变量用来记录读取到的字节个数
7.循环读取
8.利用out将图片数据输出到服务器端
9.关闭流
10.读完将读取到的文件数据发送到服务器端
11.获得字节输入流对象
12.读取服务器返回的上传状态文字
*/
public class TCPClient {
public static void main(String[] args) throws Exception{
//1.创建客户端Socket对象
Socket socket = new Socket("172.20.10.2",9999);
//3.创建字节输入流关联目标文件:要上传的文件
FileInputStream fis = new FileInputStream("H:/aaa.jpg");
//4.获得字节输出流对象
OutputStream out = socket.getOutputStream();
//5.定义字节数组存储读取到的文件数据
byte[] buf = new byte[1024];
//6.定义整型变量用来记录读取到的字节个数
int len = -1;
//7.循环读取
while ((len=fis.read(buf))!=-1){
//8.利用out将图片数据输出到服务器端
out.write(buf,0,len);
}
//9.关闭流
fis.close();
//10.读完将读取到的文件数据发送到服务器端
//11.获得字节输入流对象
InputStream in = socket.getInputStream();
//12.读取服务器返回的上传状态文字
len = in.read(buf);
System.out.println("len="+len);
System.out.println(new String(buf,0,len));
//2.关闭Socket
socket.close();
}
}
2.服务器端代码实现
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
/*
文件上传案例服务器端代码实现(先画出流程图,对着流程图写代码)
实现步骤:
1.创建ServerSocket对象
2.关闭服务器(多线程不能关)
3.等待客户端连接并获得相关的Socket对象
4.获得字节输入流对象
5.随机产生一个目标文件名
6.创建随机数对象
7.创建字节输出流关联目标文件
8.创建字节输入流对象
9.定义字节数组存储读取到客户端发送的图片数据
10.定义整型变量接收实际读取到的字节个数
11.循环读取
12.获得字节输出流对象
13.返回上传成功字符
14.关闭流和Socke
*/
public class TCPServer {
public static void main(String[] args) throws Exception{
//1.创建ServerSocket对象
ServerSocket serverSocket = new ServerSocket(9999);
//3.等待客户端连接并获得相关的Socket对象
Socket socket = serverSocket.accept();
//6.创建随机数对象
int index = new Random().nextInt(324723894);
//5.随机产生一个目标文件名
String fileName = System.currentTimeMillis()+index+".jpg";
//4.获得字节输入流对象
InputStream fis = socket.getInputStream();
//6.保存到硬盘里面的某个文件夹,需要拼接一个绝对路径
//创建目标文件对象
File destFile = new File("H:/aaa.jpg", fileName);
//7.创建字节输出流关联目标文件
FileOutputStream fos = new FileOutputStream(destFile);
//8.创建字节输入流对象
InputStream in = socket.getInputStream();
//循环读取
//9.定义字节数组存储读取到客户端发送的图片数据
byte[] buf = new byte[1024];
//10.定义整型变量接收实际读取到的字节个数
int len = -1;
//11.循环读取
while ((len=in.read(buf))!=-1){
//12.利用fos将图片数据输出到目标文件中
fos.write(buf,0,len);
}
//12.获得字节输出流对象
OutputStream out = socket.getOutputStream();
//13.返回上传成功字符
out.write("上传成功".getBytes());
//14.关闭流和Socke
fos.close();
socket.close();
//2.关闭服务器(多线程不能关)
serverSocket.close();
}
}
3.此时会出现一个问题,只考虑了上传成功的情况,那么我们如何处理上传失败的情况呢?先不抛异常,使用try...catch处理,把所有的代码都放在try...catch中。只要是进来了catch就出问题了,此时拿不到Socket,需要把前面两行代码放在外面(然后申明),然后可以利用JDK1.9新特性,将关闭服务器的代码放在小括号,即socket.close();serverSocket.close();放在小括号。
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class TCPServer {
public static void main(String[] args) throws Exception{
//1.创建ServerSocket对象
ServerSocket serverSocket = new ServerSocket(9999);
//3.等待客户端连接并获得相关的Socket对象
Socket socket = serverSocket.accept();
try(socket;serverSocket){
//6.创建随机数对象
int index = new Random().nextInt(324723894);
//5.随机产生一个目标文件名
String fileName = System.currentTimeMillis()+index+".jpg";
//4.获得字节输入流对象
InputStream fis = socket.getInputStream();
//6.保存到硬盘里面的某个文件夹,需要拼接一个绝对路径
//创建目标文件对象
File destFile = new File("H:/aaa.jpg", fileName);
//7.创建字节输出流关联目标文件
FileOutputStream fos = new FileOutputStream(destFile);
//8.创建字节输入流对象
InputStream in = socket.getInputStream();
//循环读取
//9.定义字节数组存储读取到客户端发送的图片数据
byte[] buf = new byte[1024];
//10.定义整型变量接收实际读取到的字节个数
int len = -1;
//11.循环读取
while ((len=in.read(buf))!=-1){
//12.利用fos将图片数据输出到目标文件中
fos.write(buf,0,len);
}
//12.获得字节输出流对象
OutputStream out = socket.getOutputStream();
//13.返回上传成功字符
out.write("上传成功".getBytes());
//14.关闭流和Socke
fos.close();
}catch (Exception e){
//12.获得字节输出流对象
OutputStream out = socket.getOutputStream();
//13.返回上传成功字符
out.write("上传失败".getBytes());
}
}
}
客户端发数据没有将-1发过去,则读不到数据,这时需要在客户端加一行代码
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws Exception{
//1.创建客户端Socket对象
Socket socket = new Socket("172.20.10.2",9999);
//3.创建字节输入流关联目标文件:要上传的文件
FileInputStream fis = new FileInputStream("H:/aaa.jpg");
//4.获得字节输出流对象
OutputStream out = socket.getOutputStream();
//5.定义字节数组存储读取到的文件数据
byte[] buf = new byte[1024];
//6.定义整型变量用来记录读取到的字节个数
int len = -1;
//7.循环读取
while ((len=fis.read(buf))!=-1){
//8.利用out将图片数据输出到服务器端
out.write(buf,0,len);
}
//告诉服务器端数据传输完毕,相当于输出一个结束标记给服务器端
socket.shutdownOutput();
//9.关闭流
fis.close();
//10.读完将读取到的文件数据发送到服务器端
//11.获得字节输入流对象
InputStream in = socket.getInputStream();
//12.读取服务器返回的上传状态文字
len = in.read(buf);
System.out.println("len="+len);
System.out.println(new String(buf,0,len));
//2.关闭Socket
socket.close();
}
}
文件上传案例服务器端代码实现:实现多用户上传(多线程)
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public class TCPClient {
public static void main(String[] args) throws Exception{
//1.创建客户端Socket对象
Socket socket = new Socket("172.20.10.2",9999);
//3.创建字节输入流关联目标文件:要上传的文件
FileInputStream fis = new FileInputStream("H:/aaa.jpg");
//4.获得字节输出流对象
OutputStream out = socket.getOutputStream();
//5.定义字节数组存储读取到的文件数据
byte[] buf = new byte[1024];
//6.定义整型变量用来记录读取到的字节个数
int len = -1;
//7.循环读取
while ((len=fis.read(buf))!=-1){
//8.利用out将图片数据输出到服务器端
out.write(buf,0,len);
}
//告诉服务器端数据传输完毕,相当于输出一个结束标记给服务器端
socket.shutdownOutput();
//9.关闭流
fis.close();
//10.读完将读取到的文件数据发送到服务器端
//11.获得字节输入流对象
InputStream in = socket.getInputStream();
//12.读取服务器返回的上传状态文字
len = in.read(buf);
System.out.println("len="+len);
System.out.println(new String(buf,0,len));
//2.关闭Socket
socket.close();
}
}
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Random;
public class TCPServer {
public static void main(String[] args) throws Exception{
//1.创建ServerSocket对象
ServerSocket serverSocket = new ServerSocket(9999);
System.out.println("服务器开启");
//使用死循环保证服务器永不关闭
while (true){
//3.等待客户端连接并获得相关的Socket对象
Socket socket = serverSocket.accept();
//开启线程执行上传操作
new Thread(()->{
try(socket){
//6.创建随机数对象
int index = new Random().nextInt(324723894);
//5.随机产生一个目标文件名
String fileName = System.currentTimeMillis()+index+".jpg";
//4.获得字节输入流对象
InputStream fis = socket.getInputStream();
//6.保存到硬盘里面的某个文件夹,需要拼接一个绝对路径
//创建目标文件对象
File destFile = new File("H:/aaa.jpg", fileName);
//7.创建字节输出流关联目标文件
FileOutputStream fos = new FileOutputStream(destFile);
//8.创建字节输入流对象
InputStream in = socket.getInputStream();
//循环读取
//9.定义字节数组存储读取到客户端发送的图片数据
byte[] buf = new byte[1024];
//10.定义整型变量接收实际读取到的字节个数
int len = -1;
//11.循环读取
while ((len=in.read(buf))!=-1){
//12.利用fos将图片数据输出到目标文件中
fos.write(buf,0,len);
}
//12.获得字节输出流对象
OutputStream out = socket.getOutputStream();
//13.返回上传成功字符
out.write("上传成功".getBytes());
//获得客户端ip地址
String clientIP = socket.getInetAddress().getHostAddress();
System.out.println("恭喜IP为:"+clientIP+"上传成功");
//14.关闭流和Socke
fos.close();
}catch (Exception e){
try {
//12.获得字节输出流对象
OutputStream out = socket.getOutputStream();
//13.返回上传成功字符
out.write("上传失败".getBytes());
}catch (Exception ee){
ee.printStackTrace();
}
}
}).start();
}
}
}
模拟服务器案例:
未完,待续......