rt,网上找了一些代码,但是只能发送一个文件,要么就只能关闭socket。但是这样都不完美。所以我想做一个可以想发送多少就发送多少的程序。哪个高手能告诉我该怎么做啊。有实例代码更好。[email protected](这是我的邮箱)

解决方案 »

  1.   

    没看出来你觉得主要问题是啥?一般来说,只需要发送文件前,告知目标方,比如:发送文件标识(4byte) + 文件名长度(4byte) + 文件长度(4byte) + 文件名 + 文件内容。目标方就能够处理了。
    Java的缺憾主要是因为没有C++里面的“结构”,所以对于这种定长信息的处理缺乏优势。
    但也不是啥很大问题才对。
      

  2.   

      主要问题是怎么可以使socket连续传输多个文件。
      

  3.   

    我逻辑混乱了,想不到有什么方法可以连续传输多个文件。
    以下是服务器端代码
    import java.io.BufferedInputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;public class server1 {
        int port = 8821;    void start() {
            Socket s = null;
            try {
                ServerSocket ss = new ServerSocket(port);
                while (true) {
                    // 选择进行传输的文件
                    String filePath = "D:\\BackFolder";
                    File fi = new File(filePath);                System.out.println("文件长度:" + (int) fi.length());
                    File [] f2=fi.listFiles();
                    // public Socket accept() throws
                    // IOException侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。
                    s = ss.accept();
                    System.out.println("建立socket链接");                
                    server(f2,s);
                    System.out.println("文件传输完成");
                    s.close();                
                    
                }        } catch (Exception e) {
                e.printStackTrace();
            }
        }
        public void server(File []  f2,Socket s) throws IOException
        {
            for(int i=0;i<f2.length;i++){
             File f3=f2[i];
             if(f3.isDirectory()==true)
                {
                 File [] f4=f3.listFiles();
                 server(f4,s);            
                }else{
                
             FileInputStream in = new FileInputStream(f2[i]);
             System.out.println(f2[i].getPath());
             System.out.println(f2[i].getName());
            DataInputStream dis = new DataInputStream(new BufferedInputStream(s.getInputStream()));
            dis.readByte();                
            DataInputStream fis = new DataInputStream(new BufferedInputStream(in));
            DataOutputStream ps = new DataOutputStream(s.getOutputStream());
            //将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,具体可以参见Think In Java 4th里有现成的代码。
            
            ps.writeUTF(f3.getName());
            ps.flush();
            ps.writeLong((long) f3.length());
            ps.flush();        int bufferSize = 8192;
            byte[] buf = new byte[bufferSize];        while (true) {
                int read = 0;
                if (fis != null) {
                    read = fis.read(buf);
                }            if (read == -1) {
                    break;
                }
                ps.write(buf, 0, read);
            }
            ps.flush();                
            fis.close();
            }
            }
        }
        public static void main(String arg[]) {
            new server1().start();
        }
    }
      

  4.   

    哦,看你的程序是打算 服务器端给客户端发送文件,但在逻辑切分上有些不合理。先假定你只能给一个客户端传送文件吧。这个函数:void start();(先去掉while true)
    1、等待客户端接入,也就是:ss.accept();
    2、打开发送流:DataOutputStream ps = new DataOutputStream(s.getOutputStream());
    3、获取文件列表,也就是:File [] f2=fi.listFiles();
    4、循环f2;
    5、循环中调用sendfile( f2[i], ps);
    6、关闭ps(如果你还想再干其它的事情的话,那么这个连接必须用不关闭)。然后是:void sendfile(File f, DataOutputStream ps);
    1、读取方式打开文件;
    2、获取文件大小和文件名;
    3、将文件大小和文件名大小,写入ps;
    4、将文件名写入ps;
    5、循环将整个文件内容写入ps;
    6、return。关键在你一旦从Socket中得到了输出流,在用完之前就千万别关闭它。
      

  5.   

    package fileTransfer;import java.io.BufferedInputStream;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileNotFoundException;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;public class server1 {
    int port = 8823; void start() {
    Socket s = null;
    try {
    ServerSocket ss = new ServerSocket(port);
    // 选择进行传输的文件
    String filePath = "D:\\BO";
    File fi = new File(filePath); System.out.println("文件长度:" + (int) fi.length());
    File[] f2 = fi.listFiles();
    // public Socket accept() throws
    // IOException侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。
    s = ss.accept();
    System.out.println("建立socket链接");
    // DataInputStream dis = new DataInputStream(new
    // BufferedInputStream(s.getInputStream()));
    // DataInputStream fis = new DataInputStream(new
    // BufferedInputStream(in));
    DataOutputStream ps = new DataOutputStream(s.getOutputStream());
    DataInputStream dis = new DataInputStream(new BufferedInputStream(s
    .getInputStream()));
    for (int i = 0; i < f2.length; i++) {
    File f3 = f2[i];
    if (f3.isDirectory() == true) {
    // //File [] f4=f3.listFiles();
    // sendfile(f4,ps);
    } else { // FileInputStream in = new FileInputStream(f2[i]);
    System.out.println(f2[i].getPath());
    System.out.println(f2[i].getName());
    sendfile(f2[i], ps,dis);
    }
    }
    // dis.readByte();
    System.out.println("文件传输完成");
    s.close(); } catch (Exception e) {
    e.printStackTrace();
    }
    } public void sendfile(File f2, DataOutputStream ps,DataInputStream dis ) throws IOException { FileInputStream in = new FileInputStream(f2);
    System.out.println("??????????");
    dis.readByte();
    DataInputStream fis = new DataInputStream(new BufferedInputStream(in));
    // 将文件名及长度传给客户端。这里要真正适用所有平台,例如中文名的处理,还需要加工,具体可以参见Think In Java
    // 4th里有现成的代码。
    ps.writeUTF(f2.getName());
    ps.flush();
    ps.writeLong((long) f2.length());
    ps.flush(); int bufferSize = 8192;
    byte[] buf = new byte[bufferSize]; while (true) {
    int read = 0;
    if (fis != null) {
    read = fis.read(buf);
    } if (read == -1) {
    break;
    }
    ps.write(buf, 0, read);
    }
    ps.flush();
    fis.close(); } public static void main(String arg[]) {
    new server1().start();
    }
    }
    //这是我写的。客户端该怎么循环啊。
      

  6.   

    ---------这是客户端代码
    if (cs == null)
    return;
    DataInputStream inputStream = null;
    try {
    inputStream = cs.getMessageStream();
    } catch (Exception e) {
    System.out.print("接收消息缓存错误");

    return;
    } try {
    // 本地保存路径,文件名会自动从服务器端继承而来。
    String savePath = "E:\\";
    int bufferSize = 0000;
    byte[] buf = new byte[bufferSize];
    int passedlen = 0;
    long len = 0;
    long lastPer = 0;
    long thisPer = 0;
    String fileName = "";
    fileName = inputStream.readUTF();
    savePath += fileName;
    DataOutputStream fileOut = new DataOutputStream(
    new BufferedOutputStream(new BufferedOutputStream(
    new FileOutputStream(savePath))));
    len = inputStream.readLong();

    System.out.println("文件名:" + fileName + "\t文件的长度为:" + len/1024/1024 + "M");
    System.out.println("开始接收文件..." + "");
    System.out.print("<");
    int read = 0; while (true) {

    if (inputStream != null) {
    read = inputStream.read(buf);
    }
    passedlen += read;
    if (read == -1) {
    break;
    }
    // 下面进度条本为图形界面的prograssBar做的,这里如果是打文件,
    // 可能会重复打印出一些相同的百分比
    thisPer = passedlen * 100 / len;
    if(thisPer > lastPer)
    {
    lastPer = thisPer;
    System.out.print("=" + thisPer);
    }

    fileOut.write(buf, 0, read);
    System.out.println(">");
    System.out.println("接收完成,文件存为" + savePath + "");
    //fileOut.flush();
    }
    fileOut.close();
    } catch (Exception e) {
    System.out.println("接收消息错误" + "");
    return;
    }
      

  7.   

    一个和多个没多大区别吧,你把文件放到多个byte数组中,然后依次传送就可以了,最好是封装一个类包含(文件属性信息,文件byte数据,,)
      

  8.   

    看你的代码压力很大,我写了个你参考下吧。但是要特别说明下:
    不支持多级目录处理!因为多级目录处理还涉及到要通知客户端关于子目录创建的问题。
    不支持自动删除文件!这个涉及到要跟客户端文件做比对。服务端代码:package io;import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.net.ServerSocket;
    import java.net.Socket;/**
     * 文件传输,服务端,负责将制定目录下的文件无条件发给FileClient
     */
    public class FileServer {
        public static final int PORT = 8823;    public static final String DIR_PATH = "D:\\BO\\server";    public static File rootdir = new File(DIR_PATH);    byte[] buffer = new byte[16 * 1024]; // 16K缓存大小    /**
         * @param msg 输出日志
         */
        private void log(Object msg) {
            System.out.println(msg);
        }    /**
         * 服务启动函数
         * @throws Exception 懒得写捕获异常及处理了
         */
        void start() throws Exception {
            ServerSocket serverSocket;
            Socket socket;
            while (true) {
                serverSocket = new ServerSocket(PORT);
                log("服务端就绪,等待客户端连接");            // 侦听并接受到此套接字的连接。此方法在进行连接之前一直阻塞。
                socket = serverSocket.accept();
                log("有客户端连接上来了,已建立Socket链接");            // 准备好输出(因为不关心客户端发什么信息过来,所以输入流也不管它了)
                DataOutputStream socketOut = new DataOutputStream(socket.getOutputStream());            // 借助递归处理所有的目录下的文件
                log("准备传输所有文件");
                sendAllFile(rootdir, socketOut);
                log("文件传输完成");            // 发送结束标志
                socketOut.writeLong(-1);            serverSocket.close();
            }
        }    /**
         * 借助递归处理所有的目录下的文件
         * @param fileOrDir 文件或目录
         * @param socketOut 面向FileClient的输出流
         */
        private void sendAllFile(File fileOrDir, DataOutputStream socketOut) throws Exception {
            if (fileOrDir.isDirectory()) {
                File[] fs = fileOrDir.listFiles();
                log("找到目录[" + fileOrDir.getName() + "],其下子目录及文件数:" + fs.length);
                for (int i = 0; i < fs.length; i++) {
                    sendAllFile(fs[i], socketOut);
                }
            } else {
                log("准备传输文件:" + fileOrDir.getName());
                writeOutTheFile(fileOrDir, socketOut);
            }
        }    /**
         * 文件发送
         * @param file 文件
         * @param socketOut 面向FileClient的输出流
         */
        public void writeOutTheFile(File file, DataOutputStream socketOut) throws Exception {        // 先准备好文件名和总长度信息
            String filename = file.getName();
            byte[] bytename = filename.getBytes();
            long fileSize = file.length();
            int nameSize = bytename.length;        // 1、发送长度信息
            log("发送长度信息:" + fileSize + "\t\t" + filename + ":" + nameSize);
            socketOut.writeLong(fileSize);
            socketOut.writeInt(nameSize);        // 2、发送文件名
            socketOut.write(bytename);        // 3、发送文件内容
            FileInputStream in = new FileInputStream(file);
            int size; // 记录每次读取大小
            try {
                while ((size = in.read(buffer)) > 0) {
                    socketOut.write(buffer, 0, size);
                }
            } finally {
                in.close();
            }
            socketOut.flush();        // 4、如果高兴的话,可以再发个MD5文件校验码,让FileClient去检查下所接收数据是否正确。
        }    public static void main(String arg[]) throws Exception {
            new FileServer().start();
        }
    }
      

  9.   

    【客户端代码】
    package io;import java.io.BufferedInputStream;
    import java.io.DataInputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.net.Socket;/**
     * 文件传输,客户端,负责连接FileServer并将其所传送过来的文件无条件记录下来
     */
    public class FileClient {
        public static final String SERVER = "localhost";    public static final int PORT = 8823;    public static final String DIR_PATH = "D:\\BO\\client";    public static File rootdir = new File(DIR_PATH);    byte[] buffer = new byte[16 * 1024]; // 16K缓存大小    /**
         * @param msg 输出日志
         */
        private void log(Object msg) {
            System.out.println(msg);
        }    void start() throws Exception {
            Socket socket = new Socket(SERVER, PORT);
            try {
                log("成功连接服务器端,准备接收文件");
                DataInputStream socketIn = new DataInputStream(new BufferedInputStream(socket.getInputStream()));            while (readInTheFile(rootdir, socketIn));
            } finally {
                socket.close();
            }
        }    boolean readInTheFile(File dir, DataInputStream socketIn) throws Exception {
            // 获取头部信息:文件大小、文件名长度、文件名
            long filesize = socketIn.readLong();
            if (filesize < 0) {
                log("服务器端文件发送已经结束");
                return false;
            }
            
            int namesize = socketIn.readInt();
            socketIn.read(buffer, 0, namesize);
            String filename = new String(buffer, 0, namesize);
            log("得到文件信息,文件大小:" + filesize + "\t文件名长度:" + namesize + "\t" + filename);        // 准备本地写入文件
            File file = new File(dir, filename);
            FileOutputStream out = new FileOutputStream(file);        // 从服务器端获取文件内容,并写入本地
            int size; // 记录每次读取大小
            try {
                while (true) {
                    size = (int) ((buffer.length < filesize) ? buffer.length : filesize);
                    size = socketIn.read(buffer, 0, size);
                    if (size <= 0)
                        break;
                    out.write(buffer, 0, size);
                    filesize -= size;
                }
            } finally {
                out.close();
            }
            return true;
        }    public static void main(String[] args) throws Exception {
            new FileClient().start();
        }
    }
      

  10.   

    其实这相当于你自己要定义一份协议。这边发送数据是什么结构,那边接受数据要能对应上。关于发送文件的结构,2楼已经说的很完善了。主要还是收发两边的控制,发数据,没啥说的,按照自己定义的结构逐个发送就行。收数据那边要对应上。比如说,默认第一次接收只接收一个字节的数据(二楼写的用了4个字节:发送文件标识(4byte)看你具体有多少种命令,如果觉得以后扩展功能可能很大,就多留点字节)。可以byte cmdTypeByte[] = new byte[1];然后去读出第一个字节,根据这个值来判断对方是在发送聊天内容还是在发送文件。如果是发送文件那么先再读两个8个字节,前4个字节恢复成int数值,确定文件名长度,然后再去读指定长度个字节,组合成字符串,就是你要保存的文件名。然后同理再读数据。
    如果你想做的完善些,客户端就不要着急发实际文件数据。服务端接收发送文件请求后,可以弹出个选择框,可以选择保存的路径或者说不接收数据等等。
    再完善些如果发送大文件,两边都可以加入中途停止发送功能。如果是发送文件一方停止,接收方正在接收数据,无法获得发送方已经停止发送的消息(因为没接收完文件数据,接收的所有数据都作为文件数据处理)。这个时候最好在开一个端口。有点像硬件的处理,一个端口专门做命令处理,一个端口专门做数据处理。
    做的完善些,中途停止后再重新发送文件,如果接收文件方保存的路径不变。原则上也可以做续传处理。将传了一半的文件大小发给发送方,让他直接把这个大小后面的数据发过来。接收方续写文件就行了。至于说多个文件传送,循环处理就行了。挺多就是修正下接收方是询问还是默认直接执行罢了。
      

  11.   

    嗯。成功了,谢谢各位大哥。我再把我的代码改进改进。争取做到最好。尤其是谢谢ldh911和dntg007我要努力