java socket 多线程网络传输多个文件

由于需要研究了下用 java socket 传输文件,由于需要传输多个文件,因此,采用了多线程设计。客户端每个线程创建一个 socket 连接,每个 socket 连接负责传输一个文件,服务端的ServerSocket每次 accept 一个 socket 连接,创建一个线程用于接收客户端传来的文件。

1、服务端

import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.FileOutputStream; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TransferServer { private int defaultBindPort = Constants.DEFAULT_BIND_PORT; //默认监听端口号为10000 private int tryBindTimes = 0; //初始的绑定端口的次数设定为0 private ServerSocket serverSocket; //服务套接字等待对方的连接和文件发送 private ExecutorService executorService; //线程池 private final int POOL_SIZE = 4; //单个CPU的线程池大小 /** * 不带参数的构造器,选用默认的端口号 * @throws Exception */ public TransferServer() throws Exception{ try { this.bingToServerPort(defaultBindPort); executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE); System.out.println("开辟线程数 : " + Runtime.getRuntime().availableProcessors() * POOL_SIZE); } catch (Exception e) { throw new Exception("绑定端口不成功!"); } } /** * 带参数的构造器,选用用户指定的端口号 * @param port * @throws Exception */ public TransferServer(int port) throws Exception{ try { this.bingToServerPort(port); executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE); } catch (Exception e) { throw new Exception("绑定端口不成功!"); } } private void bingToServerPort(int port) throws Exception{ try { serverSocket = new ServerSocket(port); System.out.println(port); System.out.println("服务启动!"); } catch (Exception e) { this.tryBindTimes = this.tryBindTimes + 1; port = port + this.tryBindTimes; if(this.tryBindTimes >= 20){ throw new Exception("您已经尝试很多次了,但是仍无法绑定到指定的端口!请重新选择绑定的默认端口号"); } //递归绑定端口 this.bingToServerPort(port); } } public void service(){ Socket socket = null; while (true) { try { socket = serverSocket.accept(); executorService.execute(new Handler(socket)); } catch (Exception e) { e.printStackTrace(); } } } class Handler implements Runnable{ private Socket socket; public Handler(Socket socket){ this.socket = socket; } public void run() { System.out.println("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort()); DataInputStream dis = null; DataOutputStream dos = null; int bufferSize = 8192; byte[] buf = new byte[bufferSize]; try { dis = new DataInputStream(new BufferedInputStream(socket.getInputStream())); String savePath = Constants.RECEIVE_FILE_PATH + dis.readUTF(); long length = dis.readLong(); dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savePath))); int read = 0; long passedlen = 0; while ((read = dis.read(buf)) != -1) { passedlen += read; dos.write(buf, 0, read); System.out.println("文件[" + savePath + "]已经接收: " + passedlen * 100L/ length + "%"); } System.out.println("文件: " + savePath + "接收完成!"); } catch (Exception e) { e.printStackTrace(); System.out.println("接收文件失败!"); }finally{ try { if(dos != null){ dos.close(); } if(dis != null){ dis.close(); } if(socket != null){ socket.close(); } } catch (Exception e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception{ new TransferServer().service(); } }

2、客户端 import java.io.BufferedInputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.net.Socket; import java.util.ArrayList; import java.util.Random; import java.util.Vector; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; public class TransferClient { private static ArrayList<String> fileList = new ArrayList<String>(); private String sendFilePath = Constants.SEND_FILE_PATH; /** * 带参数的构造器,用户设定需要传送文件的文件夹 * @param filePath */ public TransferClient(String filePath){ getFilePath(filePath); } /** * 不带参数的构造器。使用默认的传送文件的文件夹 */ public TransferClient(){ getFilePath(sendFilePath); } public void service(){ ExecutorService executorService = Executors.newCachedThreadPool(); Vector<Integer> vector = getRandom(fileList.size()); for(Integer integer : vector){ String filePath = fileList.get(integer.intValue()); executorService.execute(sendFile(filePath)); } } private void getFilePath(String dirPath){ File dir = new File(dirPath); File[] files = dir.listFiles(); if(files == null){ return; } for(int i = 0; i < files.length; i++){ if(files[i].isDirectory()){ getFilePath(files[i].getAbsolutePath()); } else { fileList.add(files[i].getAbsolutePath()); } } } private Vector<Integer> getRandom(int size){ Vector<Integer> v = new Vector<Integer>(); Random r = new Random(); boolean b = true; while(b){ int i = r.nextInt(size); if(!v.contains(i)) v.add(i); if(v.size() == size) b = false; } return v; } private static Runnable sendFile(final String filePath){ return new Runnable(){ private Socket socket = null; private String ip ="localhost"; private int port = 10000; public void run() { System.out.println("开始发送文件:" + filePath); File file = new File(filePath); if(createConnection()){ int bufferSize = 8192; byte[] buf = new byte[bufferSize]; try { DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath))); DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); dos.writeUTF(file.getName()); dos.flush(); dos.writeLong(file.length()); dos.flush(); int read = 0; int passedlen = 0; long length = file.length(); //获得要发送文件的长度 while ((read = fis.read(buf)) != -1) { passedlen += read; System.out.println("已经完成文件 [" + file.getName() + "]百分比: " + passedlen * 100L/ length + "%"); dos.write(buf, 0, read); } dos.flush(); fis.close(); dos.close(); socket.close(); System.out.println("文件 " + filePath + "传输完成!"); } catch (Exception e) { e.printStackTrace(); } } } private boolean createConnection() { try { socket = new Socket(ip, port); System.out.println("连接服务器成功!"); return true; } catch (Exception e) { System.out.println("连接服务器失败!"); return false; } } }; } public static void main(String[] args){ new TransferClient().service(); } }

3、常量类

public interface Constants { public final static String RECEIVE_FILE_PATH = "E:\\receive\\"; public final static String SEND_FILE_PATH = "E:\\send"; public final static int DEFAULT_BIND_PORT = 10000; }

<pre name="code" id="best-content-1009763504" class="best-text mb-10" style="margin-top:0px; margin-bottom:10px; padding:0px; font-family:arial,’courier new’,courier,宋体,monospace; white-space:pre-wrap; word-wrap:break-word; font-size:14px; line-height:24px; background-color:rgb(255,252,246)"></pre> <pre></pre> <pre></pre> <pre></pre>

你挤进地铁时,西藏的山鹰一直盘旋云端,

java socket 多线程网络传输多个文件

相关文章:

你感兴趣的文章:

标签云: