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. cmstop中实例化controller_admin_content类传递$this,其构造方法中接收到的是--名为cmstop的参数--包含cmstop中所有属性

    主程序cmstop类,实例化controller_admin_content类(接收请求后拼接的).传递cmstop所有属性过去.controller_admin_content.构造方法中接收到名称 ...

  2. CentOS中由一般用户切换为root用户

    --->http://www.centoscn.com/CentOS/help/2014/0624/3173.html 1.打开终端,提示符为“$”,表明该用户为普通用户,此时,直接输su,回车 ...

  3. 经典.net面试题目(3)

    1. asp.net中web应用程序获取数据的流程: A.Web Page B.Fill  C.Sql05  D.Data Sourse  E.DataGrid  F.DataSet  G.Selec ...

  4. 使用SQL Server 2000索引视图提高性能

    什么是索引视图? 许多年来,Microsoft? SQL Server? 一直都提供创建虚拟表(称为视图)的功能.在过去,这些视图主要有两种用途: 提供安全机制,将用户限制在一个或多个基表中的数据的某 ...

  5. java问题诊断

    http://techblog.youdao.com/?p=961 http://linuxtools-rst.readthedocs.org/zh_CN/latest/advance/03_opti ...

  6. win8.1下安装ubuntu 14.0 4LTS

    1.前奏 电脑上已经安装了win8.1系统 2.准备工作 关闭win8.1的快速启动 步骤: 控制面板->电源选项->选择电源按钮的功能->更改不可用的设置,然后把"启用快 ...

  7. phpStudy环境配置多个站点,绑定域名

    经常做网站的朋友,往往要在自已的电脑同时建立多个站点,而phpstudy这款软件就能很好的解决这个问题,大家看下图 点击上图中的 其它选项菜单 ,就会弹出下面的对话框,然后点击 站点域名管理 然 后在 ...

  8. OVS - commands

    journalctl -t ovs-vswitchd ovs-vsctl show ovs-ofctl show br0 set vlanid ovs-vsctl set port eth0 tag= ...

  9. 初识Jmeter(一)

    倒霉熊的推荐: 文本学习网址:http://m.open-open.com/m/doc/category/105 视频学习网址: 软件学习网:http://www.ask3.cn/index.html ...

  10. 第三方 XListview 上拉加载、下拉刷新、分页加载和Gson解析

    注意:此Demo用的是第三方的Xlistview.jar,需要复制me文件夹到项目中,两个XML布局文件和一张图片 把下面的复制到String中 <string name="xlist ...