Java Socket 多线程网络传输多个文件

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

1、服务端

  1. import java.io.BufferedInputStream;    
  2. import java.io.BufferedOutputStream;    
  3. import java.io.DataInputStream;    
  4. import java.io.DataOutputStream;    
  5. import java.io.FileOutputStream;    
  6. import java.net.ServerSocket;    
  7. import java.net.Socket;    
  8. import java.util.concurrent.ExecutorService;    
  9. import java.util.concurrent.Executors;    
  10.     
  11. public class TransferServer {    
  12.     
  13.     private int defaultBindPort = Constants.DEFAULT_BIND_PORT;    //默认监听端口号为10000     
  14.     private int tryBindTimes = 0;           //初始的绑定端口的次数设定为0     
  15.         
  16.     private ServerSocket serverSocket;      //服务套接字等待对方的连接和文件发送     
  17.         
  18.     private ExecutorService executorService;    //线程池     
  19.     private final int POOL_SIZE = 4;            //单个CPU的线程池大小      
  20.         
  21.     /**  
  22.      * 不带参数的构造器,选用默认的端口号  
  23.      * @throws Exception  
  24.      */    
  25.     public TransferServer() throws Exception{    
  26.         try {    
  27.             this.bingToServerPort(defaultBindPort);    
  28.             executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);    
  29.             System.out.println("开辟线程数 : " + Runtime.getRuntime().availableProcessors() * POOL_SIZE);    
  30.         } catch (Exception e) {    
  31.             throw new Exception("绑定端口不成功!");    
  32.         }    
  33.     }    
  34.         
  35.     /**  
  36.      * 带参数的构造器,选用用户指定的端口号  
  37.      * @param port  
  38.      * @throws Exception  
  39.      */    
  40.     public TransferServer(int port) throws Exception{    
  41.         try {    
  42.             this.bingToServerPort(port);    
  43.             executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * POOL_SIZE);    
  44.         } catch (Exception e) {    
  45.             throw new Exception("绑定端口不成功!");    
  46.         }    
  47.     }    
  48.         
  49.     private void bingToServerPort(int port) throws Exception{    
  50.         try {    
  51.             serverSocket = new ServerSocket(port);    
  52.             System.out.println(port);    
  53.             System.out.println("服务启动!");    
  54.         } catch (Exception e) {    
  55.             this.tryBindTimes = this.tryBindTimes + 1;    
  56.             port = port + this.tryBindTimes;    
  57.             if(this.tryBindTimes >= 20){    
  58.                 throw new Exception("您已经尝试很多次了,但是仍无法绑定到指定的端口!请重新选择绑定的默认端口号");    
  59.             }    
  60.             //递归绑定端口     
  61.             this.bingToServerPort(port);    
  62.         }    
  63.     }    
  64.         
  65.     public void service(){    
  66.         Socket socket = null;    
  67.         while (true) {    
  68.             try {    
  69.                 socket = serverSocket.accept();    
  70.                 executorService.execute(new Handler(socket));    
  71.             } catch (Exception e) {    
  72.                 e.printStackTrace();    
  73.             }    
  74.         }    
  75.     }    
  76.         
  77.     
  78.     class Handler implements Runnable{    
  79.         private Socket socket;    
  80.             
  81.         public Handler(Socket socket){    
  82.             this.socket = socket;    
  83.         }    
  84.     
  85.         public void run() {    
  86.                 
  87.             System.out.println("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());    
  88.                 
  89.             DataInputStream dis = null;    
  90.             DataOutputStream dos = null;    
  91.     
  92.             int bufferSize = 8192;    
  93.             byte[] buf = new byte[bufferSize];    
  94.                 
  95.             try {    
  96.                 dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));    
  97.                 String savePath = Constants.RECEIVE_FILE_PATH + dis.readUTF();    
  98.                 long length = dis.readLong();    
  99.                 dos = new DataOutputStream(new BufferedOutputStream(new FileOutputStream(savePath)));    
  100.                     
  101.                 int read = 0;    
  102.                 long passedlen = 0;    
  103.                 while ((read = dis.read(buf)) != -1) {    
  104.                     passedlen += read;    
  105.                     dos.write(buf, 0, read);    
  106.                     System.out.println("文件[" + savePath + "]已经接收: " + passedlen * 100L/ length + "%");    
  107.                 }    
  108.                 System.out.println("文件: " + savePath + "接收完成!");    
  109.                     
  110.             } catch (Exception e) {    
  111.                 e.printStackTrace();    
  112.                 System.out.println("接收文件失败!");    
  113.             }finally{    
  114.                 try {    
  115.                     if(dos != null){    
  116.                         dos.close();    
  117.                     }    
  118.                     if(dis != null){    
  119.                         dis.close();    
  120.                     }    
  121.                     if(socket != null){    
  122.                         socket.close();    
  123.                     }    
  124.                 } catch (Exception e) {    
  125.                     e.printStackTrace();    
  126.                 }    
  127.             }    
  128.         }    
  129.     }    
  130.         
  131.     public static void main(String[] args) throws Exception{    
  132.         new TransferServer().service();    
  133.     }    
  134. }   
    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、客户端

  1. import java.io.BufferedInputStream;    
  2. import java.io.DataInputStream;    
  3. import java.io.DataOutputStream;    
  4. import java.io.File;    
  5. import java.io.FileInputStream;    
  6. import java.net.Socket;    
  7. import java.util.ArrayList;    
  8. import java.util.Random;    
  9. import java.util.Vector;    
  10. import java.util.concurrent.ExecutorService;    
  11. import java.util.concurrent.Executors;    
  12.     
  13.     
  14. public class TransferClient {    
  15.     
  16.     private static ArrayList<String> fileList = new ArrayList<String>();    
  17.         
  18.     private String sendFilePath = Constants.SEND_FILE_PATH;    
  19.         
  20.     /**  
  21.      * 带参数的构造器,用户设定需要传送文件的文件夹  
  22.      * @param filePath  
  23.      */    
  24.     public TransferClient(String filePath){    
  25.         getFilePath(filePath);    
  26.     }    
  27.         
  28.     /**  
  29.      * 不带参数的构造器。使用默认的传送文件的文件夹  
  30.      */    
  31.     public TransferClient(){    
  32.         getFilePath(sendFilePath);    
  33.     }    
  34.         
  35.     public void service(){    
  36.         ExecutorService executorService = Executors.newCachedThreadPool();    
  37.         Vector<Integer> vector = getRandom(fileList.size());    
  38.         for(Integer integer : vector){    
  39.             String filePath = fileList.get(integer.intValue());    
  40.             executorService.execute(sendFile(filePath));    
  41.         }    
  42.     }    
  43.         
  44.     
  45.     private void getFilePath(String dirPath){    
  46.         File dir = new File(dirPath);    
  47.         File[] files = dir.listFiles();    
  48.         if(files == null){    
  49.             return;    
  50.         }    
  51.         for(int i = 0; i < files.length; i++){    
  52.             if(files[i].isDirectory()){    
  53.                 getFilePath(files[i].getAbsolutePath());    
  54.             }    
  55.             else {    
  56.                 fileList.add(files[i].getAbsolutePath());    
  57.             }    
  58.         }    
  59.     }    
  60.         
  61.     private Vector<Integer> getRandom(int size){    
  62.         Vector<Integer> v = new Vector<Integer>();    
  63.         Random r = new Random();    
  64.         boolean b = true;    
  65.         while(b){    
  66.             int i = r.nextInt(size);    
  67.             if(!v.contains(i))    
  68.                 v.add(i);    
  69.             if(v.size() == size)    
  70.                 b = false;    
  71.         }    
  72.         return v;    
  73.     }        
  74.         
  75.     private static Runnable sendFile(final String filePath){    
  76.         return new Runnable(){    
  77.                 
  78.             private Socket socket = null;    
  79.             private String ip ="localhost";    
  80.             private int port = 10000;    
  81.                 
  82.             public void run() {    
  83.                 System.out.println("开始发送文件:" + filePath);    
  84.                 File file = new File(filePath);    
  85.                 if(createConnection()){    
  86.                     int bufferSize = 8192;    
  87.                     byte[] buf = new byte[bufferSize];    
  88.                     try {    
  89.                         DataInputStream fis = new DataInputStream(new BufferedInputStream(new FileInputStream(filePath)));    
  90.                         DataOutputStream dos = new DataOutputStream(socket.getOutputStream());    
  91.                             
  92.                         dos.writeUTF(file.getName());    
  93.                         dos.flush();    
  94.                         dos.writeLong(file.length());    
  95.                         dos.flush();    
  96.                             
  97.                         int read = 0;    
  98.                         int passedlen = 0;    
  99.                         long length = file.length();    //获得要发送文件的长度     
  100.                         while ((read = fis.read(buf)) != -1) {    
  101.                             passedlen += read;    
  102.                             System.out.println("已经完成文件 [" + file.getName() + "]百分比: " + passedlen * 100L/ length + "%");    
  103.                             dos.write(buf, 0, read);    
  104.                         }    
  105.     
  106.                        dos.flush();    
  107.                        fis.close();    
  108.                        dos.close();    
  109.                        socket.close();    
  110.                        System.out.println("文件 " + filePath + "传输完成!");    
  111.                     } catch (Exception e) {    
  112.                         e.printStackTrace();    
  113.                     }    
  114.                 }    
  115.             }    
  116.                 
  117.             private boolean createConnection() {    
  118.                 try {    
  119.                     socket = new Socket(ip, port);    
  120.                     System.out.println("连接服务器成功!");    
  121.                     return true;    
  122.                 } catch (Exception e) {    
  123.                     System.out.println("连接服务器失败!");    
  124.                     return false;    
  125.                 }     
  126.             }    
  127.                 
  128.         };    
  129.     }    
  130.         
  131.     public static void main(String[] args){    
  132.         new TransferClient().service();    
  133.     }    
  134. }  
    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、常量类

  1. public interface Constants {    
  2.     
  3.     public final static String RECEIVE_FILE_PATH = "E:\\receive\\";    
  4.         
  5.     public final static String SEND_FILE_PATH = "E:\\send";    
  6.         
  7.     public final static int DEFAULT_BIND_PORT = 10000;    
  8. }    
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值