http://blog.csdn.net/njchenyi/article/details/9072845

2013-06-10 21:26 3596人阅读 评论(1) 收藏 举报
 分类:
JAVA(158) 

由于需要研究了下用 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 多线程网络传输多个文件的更多相关文章

  1. java Socket多线程聊天程序

    参考JAVA 通过 Socket 实现 TCP 编程 参考java Socket多线程聊天程序(适合初学者) 以J2SDK-1.3为例,Socket和ServerSocket类库位于java.net包 ...

  2. Java中HTTP网络传输中文编码问题

    Java中HTTP网络传输中文编码问题 1.java中new String(str.getBytes("utf-8"),"iso-8859-1")编码详解 前提 ...

  3. python+socket实现网络信息交互及文件传输

    Socket 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket. Socket又称"套接字",应用程序通常通过"套接字" ...

  4. Java Socket编程----网络基础

    详见:https://www.cnblogs.com/rocomp/p/4790340.html Java最初是作为网络编程语言出现的,其对网络提供了高度的支持,使得客户端和服务器的沟通变成了现实,而 ...

  5. java--基于socket的网络传输开发

    继http://blog.csdn.net/gaopeng0071/article/details/10959845此文章内容展开的研究. socket传输是基于tcp的网络传输协议进行的传输,tcp ...

  6. Java Socket通讯---网络基础

    java socket 通讯 参考慕课网:http://www.imooc.com/learn/161 一.网络基础知识 1.1 通讯示意图 1.2 TCP/IP协议 TCP/IP是世界上应用最为广泛 ...

  7. java socket编程(网络编程)

    一,网络编程中两个主要的问题 一个是如何准确的定位网络上一台或多台主机,另一个就是找到主机后如何可靠高效的进行数据传输. 在TCP/IP协议中IP层主要负责网络主机的定位,数据传输的路由,由IP地址可 ...

  8. Java Socket 多线程聊天室

    本来这次作业我是想搞个图形界面的,然而现实情况是我把题意理解错了,于是乎失去了最初的兴致,还是把程序变成了功能正确但是“UI”不友好的console了,但是不管怎么样,前期的图形界面的开发还是很有收获 ...

  9. Java Socket实战之三 传输对象

    首先需要一个普通的对象类,由于需要序列化这个对象以便在网络上传输,所以实现java.io.Serializable接口就是必不可少的了,入下: public class User implements ...

随机推荐

  1. ocs添加仓库受限问题

    添加仓库时受限出现以下问题 如图: 解决方法 修改app\ome\lib\branch\func.php文件的allow_use_num方法 /** * 允许使用的仓库数 * @access publ ...

  2. excel中自动变为插入语句的写法

    =concatenate("insert into t(b,c) values('",b1,"','",c1,"');")

  3. 好用的API文档--在线版

    安卓在线api http://www.android-doc.com/reference/packages.html

  4. 解读QML之一

    http://cache.baiducontent.com/c?m=9d78d513d98002b8599dcb201a17a7374408c6347691c4523f8a9c12d522195646 ...

  5. external 里面文件的介绍

    搞了半天android,竟然对external下的库一无所知?不能容忍! 马上解决: android-mock:编译为java静态库.说明:Android Mock is a framework fo ...

  6. Delphi XE2 生成的.exe 在未安装有Delphi的电脑上运行提示 “丢失 rtl160.bpl”

    解决方案: XE2中加入了多平台的概念,默认的Release模式,也是带包编译,带运行时库的,所以,需要手工设置一下工程选项: 打开工程以后,Project-->Options-->左侧树 ...

  7. CSS中常见中文字体的英文名称(Microsoft YaHei,SimHei)

    Mac OS的一些: 华文细黑:STHeiti Light [STXihei]华文黑体:STHeiti华文楷体:STKaiti华文宋体:STSong华文仿宋:STFangsong儷黑 Pro:LiHe ...

  8. 静默方式安装window oracle

    1. setup.exe -silent -responseFile "C:\app\software\WIN64_11204\RSP\db_install_window.rsp" ...

  9. CSS中如何把Span标签设置为固定宽度

    一.形如<span>ABC</span>独立行设置SPAN为固定宽度方法如下: span {width:60px; text-align:center; display:blo ...

  10. UVALive 2678 大于s的最短子序列和

    input n s 10<=n<=100000,s<1e9 a1 a2 ... an  ai<=10000 output 大于s的最短子序列和的长度,没有输出0 #includ ...