对于上传文件的多线程程序,客户端不存在多线程,主要是服务器需要利用线程池,思路:
1、客户端上传程序编写
建立连接,利用tcp套接字
读取本地流,即待上传的文件,优先使用高效流
读取文件数据并写入到tcp流中
上传完成后断开tcp流,避免服务器一直等待
接收服务器端返回信息,并完成上传任务
Socket socket = new Socket("192.168.0.103", 9000);
BufferedInputStream inputStream = new BufferedInputStream(new FileInputStream("/Users/ryan/Public/netcode/src/com/doit/netdemo/mutithreadupload/comm.gif"));
OutputStream outputStream = socket.getOutputStream();
//每次写入8k
byte[] data = new byte[1024*8];
int len = 0;
//开始上传
while((len=inputStream.read(data))!=-1){
outputStream.write(data,0,len);
}
//上传完成
socket.shutdownOutput();
//接收反馈
len = socket.getInputStream().read(data);
System.out.println(new String(data,0,len));
inputStream.close();
socket.close();
2、服务端多线程编写:每一个客户端都是通过socket建立连接
建立一个socket成员变量,通过构造器传入
建立一个接收程序,实现Runnable接口
重写run方法
设置接收的文件夹与文件名,自动生成,利用时间戳
创建高效输出流(注意,当文件较多时,写入时必须加入Thread.sleep(200)进行延缓写入,避免因网速过快时,导致文件的IO输出瓶颈出现定入不完整,文件无法打开的情况)
接收tcp输入流,并边接收边写入
写入完成后回写写入成功标记
public class UploadServer implements Runnable {
private Socket socket = null;
public UploadServer(Socket socket) {
this.socket = socket;
}
public void run() {
try {
String filename = "/Users/ryan/Desktop/newimg"+File.separator+"doit" + System.currentTimeMillis() + new Random().nextInt(9999)+".jpg";
BufferedOutputStream outputStream = new BufferedOutputStream(new FileOutputStream(filename));
InputStream inputStream = socket.getInputStream();
byte[] data = new byte[1024*8];
int len = 0;
while((len = inputStream.read(data))!=-1){
outputStream.write(data,0,len);
}
// outputStream.flush();
//回写成功
socket.getOutputStream().write("上传OK".getBytes());
//关闭高速流前flush进磁盘中去
outputStream.close();
socket.close();
} catch (IOException e) {
}
}
}
3、利用线程池,调用服务端程序
创建线程池
建立服务器监听端口
将服务端设置为一直接收
调用服务端程序
ExecutorService executorService = Executors.newFixedThreadPool(5);
ServerSocket serverSocket = new ServerSocket(9000);
while (true) {
Socket accept = serverSocket.accept();
executorService.execute(new UploadServer(accept));
}