`

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

    博客分类:
  • J2SE
阅读更多
由于需要研究了下用 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;  
    }  
分享到:
评论

相关推荐

    java socket多线程文件传输实例项目

    总结来说,Java Socket多线程文件传输实例项目是一个综合性的实践,涵盖了网络编程、多线程并发控制以及文件I/O等多个核心Java技术。通过这个项目,开发者可以深入理解如何在实际场景中运用这些技术,解决并发文件...

    java socket 多线程实例

    Java Socket是Java网络编程的基础,它提供了在网络之间进行通信的能力。多线程是Java编程中的一个重要概念,允许程序同时执行多个...通过这个实例,我们可以深入理解Java Socket和多线程在实际网络应用程序中的应用。

    java socket 多线程并发控制 hibernate mysql

    总的来说,本项目结合了Java的Socket通信、多线程并发控制、Hibernate ORM以及MySQL数据库,构建了一个能处理并发网络请求并存储信息的系统。这样的设计使得系统具备良好的扩展性和健壮性,能够高效地服务大量用户。...

    Java Socket 多线程实现文件传输

    Java Socket 多线程实现文件传输是一个常见的网络编程...通过以上介绍,你应该对Java Socket多线程实现文件传输有了基本的理解。实际开发中,还需要根据具体需求进行调整和优化,例如添加进度显示、文件校验等功能。

    \\(^_^)/ Java 使用Socket多线程传输整个文件夹

    在Java编程中,Socket通信是网络应用程序之间进行数据交换的基础,尤其在文件传输...总的来说,使用Java的Socket和多线程技术实现文件夹传输是一项复杂的任务,需要掌握网络编程、多线程、文件操作等多个方面的知识。

    java socket多线程文件上传下载实例项目

    Java Socket多线程文件上传下载实例项目是一种基于Java网络编程技术实现的,旨在处理大量并发连接的文件传输服务。在本项目中,Socket是客户端与服务器之间通信的基础,它允许两个应用程序通过网络交换数据。多线程...

    Java Socket聊天和文件传输工具(更新)

    总的来说,这个Java Socket聊天和文件传输工具是一个很好的学习和实践案例,涵盖了网络编程、多线程、文件I/O等多个Java核心技术。无论是对初学者还是经验丰富的开发者来说,都能从中受益,提升自己的技能。通过深入...

    JAVA Socket编程实现文件上传

    以上就是使用Java Socket编程实现文件上传涉及到的主要知识点,包括Socket通信机制、文件I/O、数据库操作、异常处理、多线程、安全性和性能优化等方面。理解并掌握这些内容,对于开发高效、可靠的文件上传系统至关...

    java,socket多线程一对一聊天

    总的来说,"java,socket多线程一对一聊天"项目涵盖了Java网络编程的基础知识,包括Socket通信、多线程以及基本的消息传递机制。虽然不支持并发,但对于学习和理解这些基本概念仍然很有价值。在实际应用中,可以通过...

    Java Socket聊天和文件传输工具

    这个Java Socket工具的实现涉及到了网络编程、多线程、I/O流和文件操作等多个Java核心技术,对于学习和理解Java网络编程有很好的实践价值。如果你对这些技术感兴趣,可以通过编写自己的Socket程序进行实践,加深理解...

    java多线程文件传输(基于swing)

    **打包生成的jar文件**(多线程传输.jar)是一个可执行的Java程序,包含了项目的所有类和资源,用户可以直接运行它,无需编译源代码。而FileTransfer.zip可能是项目源代码的压缩包,包含.java文件和其他必要的配置...

    java socket 多线程通讯示例

    总的来说,Java Socket多线程通信是一种强大的工具,用于构建分布式系统和网络应用。理解如何创建和管理Socket连接,以及如何在多线程环境下处理这些连接,是成为熟练的Java网络程序员的关键步骤。通过实践和理解...

    java socket多线程聊天

    Java Socket多线程聊天程序是一种实现网络通信的基本方式,它基于TCP/IP协议,允许两台计算机之间进行双向数据传输。在这个简单的两人对话程序中,我们主要涉及到以下知识点: 1. **Socket**: Java中的Socket类是...

    java多线程网络传输文件(非同步)

    总的来说,"java多线程网络传输文件(非同步)"这个主题涉及到Java多线程、Socket编程以及文件I/O等核心知识。通过多线程实现并发处理客户端请求,利用Socket进行网络通信,以及处理文件的读写操作,这些是构建一个...

    java Socket多线程通讯实例

    总结起来,Java Socket多线程通讯实例展示了如何利用Java的网络编程API实现TCP通信,并通过多线程处理并发连接,这在构建例如QQ这样的聊天应用时是非常重要的技术。通过这种方式,服务端能够有效地管理大量并发的...

    Java Socket 多线程通信

    综上所述,Java Socket结合多线程技术,使得我们可以构建能够高效处理多个客户端连接的服务端应用程序,实现自定义对象的网络传输,这对于开发分布式系统或网络应用具有重要意义。在实际项目中,还需要考虑安全性、...

    Java Socket学习---单线程阻塞

    在Java编程语言中,Socket是实现网络通信的基本组件。"Java Socket学习---单线程阻塞"这个主题主要探讨了如何使用Java的Socket类进行单线程的阻塞式通信,这种模式通常用于简单的客户端-服务器应用。在这个场景中,...

Global site tag (gtag.js) - Google Analytics