8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

Java通过套接字进行多文件传输

RaytheonXie-MSFT 1月前

33 0

好的,尝试通过套接字传输指定目录中的文件,从数组列表中删除目录对象,这样就只剩下文件,然后通过同一个套接字逐个传输它们。数组...

好的,尝试通过套接字传输指定目录中的文件,从数组列表中删除目录对象,这样只剩下文件,然后通过同一个套接字逐个传输它们。这里的数组列表只填充了文件,没有目录。以下分别是客户端和服务器的接收和发送代码。代码运行良好,没有错误,除了所有数据都被写入第一个文件。后续文件在服务器文件夹中创建,但它们是 0 字节。任何输入都将不胜感激。

这是接收文件的服务器代码

public void receive(){


    try {
        DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
//read the number of files from the client
        int number = dis.readInt();
        ArrayList<File>files = new ArrayList<File>(number);
        System.out.println("Number of Files to be received: " +number);
        //read file names, add files to arraylist
        for(int i = 0; i< number;i++){
            File file = new File(dis.readUTF());
            files.add(file);
        }
        int n = 0;
        byte[]buf = new byte[4092];

        //outer loop, executes one for each file
        for(int i = 0; i < files.size();i++){

            System.out.println("Receiving file: " + files.get(i).getName());
            //create a new fileoutputstream for each new file
            FileOutputStream fos = new FileOutputStream("C:\\users\\tom5\\desktop\\salestools\\" +files.get(i).getName());
            //read file
            while((n = dis.read(buf)) != -1){
                fos.write(buf,0,n);
                fos.flush();
            }
            fos.close();
        }

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();

    }


}

这是发送文件的客户端代码

public void send(ArrayList<File>files){

    try {
        DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
        DataOutputStream dos = new DataOutputStream(new BufferedOutputStream(socket.getOutputStream()));
        System.out.println(files.size());
//write the number of files to the server
        dos.writeInt(files.size());
        dos.flush();

        //write file names 
        for(int i = 0 ; i < files.size();i++){
            dos.writeUTF(files.get(i).getName());
            dos.flush();
        }

        //buffer for file writing, to declare inside or outside loop?
        int n = 0;
        byte[]buf = new byte[4092];
        //outer loop, executes one for each file
        for(int i =0; i < files.size(); i++){

            System.out.println(files.get(i).getName());
            //create new fileinputstream for each file
            FileInputStream fis = new FileInputStream(files.get(i));

            //write file to dos
            while((n =fis.read(buf)) != -1){
                dos.write(buf,0,n);
                dos.flush();

            }
            //should i close the dataoutputstream here and make a new one each time?
        }
        //or is this good?
        dos.close();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }


}
帖子版权声明 1、本帖标题:Java通过套接字进行多文件传输
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由RaytheonXie-MSFT在本站《sockets》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 我创建了服务器和客户端。它们正在建立连接,之后服务器每秒发送 1MB 的文本文件。服务器和客户端代码如下。我进行了长时间测试,发现没有数据丢失。我对上面的答案做了一些修改。

    服务器代码:

    package com.dd.server;
    
    import java.io.BufferedInputStream;
    import java.io.BufferedReader;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileReader;
    import java.io.IOException;
    import java.io.OutputStream;
    import java.net.ServerSocket;
    import java.net.Socket;
    import java.nio.file.Files;
    import java.nio.file.Paths;
    import java.util.concurrent.TimeUnit;
    
    public class Server {
    
    public static void main(String[] args) throws InterruptedException {
        try {
            byte[] done = new byte[3];
            String str = "done";  //randomly anything
            done = str.getBytes();
            ServerSocket ss = new ServerSocket(5000); 
            Socket socket = ss.accept();
            byte[] mybytearray = new byte[4096];
            OutputStream os = socket.getOutputStream();
           
            TimeUnit.SECONDS.sleep(5);
            while(true) {
                DataOutputStream dos = new DataOutputStream(os);
                File myFile= new File("I:\\MY-LEARNINGS\\JAVA\\Workspace\\server\\src\\com\\dd\\server\\gistfile1.txt");
                dos.writeUTF(myFile.getName());     
                dos.writeLong(myFile.length());
                FileInputStream fis = new FileInputStream(myFile);  
                BufferedInputStream bis = new BufferedInputStream(fis);
                DataInputStream dis = new DataInputStream(bis);
                int read;
                System.out.println("---------File Writing started----------");
                int count = 0;
                while((read = dis.read(mybytearray)) != -1){
                    dos.write(mybytearray, 0, read);
                    dos.flush();
                    ++count;
                    System.out.println("Writing sub component of file. Step : "+count);
                }
                System.out.println("---------File Writing ended----------");
                System.out.println("Flushing data DONE command sent.");
                dis.close();
                bis.close();
                fis.close();
                TimeUnit.SECONDS.sleep(1);
                System.out.println("File transfer has been completed.");
                dos.write(done, 0, 3);
                dos.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
      }
    }
    

    客户代码:

     package clientcom.dd.clent;
    
     import java.io.DataInputStream;
     import java.io.FileOutputStream;
     import java.io.IOException;
     import java.io.InputStream;
     import java.io.OutputStream;
     import java.net.Socket;
    
    public class Client {
    
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 5000);
            InputStream in = socket.getInputStream();
            DataInputStream dis = new DataInputStream(in);
            while(true) {
                FileOutputStream fos = 
                        new FileOutputStream("I:\\MY-LEARNINGS\\JAVA\\Workspace\\client\\"+System.currentTimeMillis()+"-data.txt");
                int read = 0;
                byte[] mybytearray = new byte[4096];
                while ((read = dis.read(mybytearray)) != -1 && read != 3) {
                    fos.write(mybytearray, 0, read);
                    fos.flush();
                }
                fos.close();
                //System.out.println("The value of read : "+read);
               // System.out.println("File has been received successfully.");
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
    }
    
  • 不过,读了上面的帖子,其中 Math.min 被添加到 while((n = dis.read(buf,0,Math.min(n, FileSizes[i]))。这完全解决了问题,但在这个过程中却弄乱了我的大脑

  • 哦,对了,例如,接收 5 个文件,有时它会在前 3 次迭代中接收所有字节,而最后 2 个文件将是 0 个字节,有时它会在第 4 次迭代中接收字节。非常随机

  • 好的,我也试过了,但丢失/增加了几个字节。只需检查一下传输的最后一个文件,是否丢失了几个字节?

  • 嗯,我现在发送文件大小并将其存储在 int 数组中。我将其添加到我的服务器 while 循环中,while((n = dis.read(buf)) != -1 && bytesRead < fileSize));

  • 感谢您的问题,我学到了一些新东西,您要求在每次文件传输后关闭 DataOutputStream,它实际上会关闭底层流,因此套接字会被关闭。Close()-关闭此输出流并释放与该流相关的任何系统资源。Javadocs。

  • 我这样做了,效果很好,你可以看看:

    发送

    byte[] done = new byte[3];
    String str = "done";  //randomly anything
    done = str.getBytes();
    for (int i = 0; i < files.size(); i++) {
        System.out.println(files.get(i).getName());
        FileInputStream fis = new FileInputStream(files.get(i));
        while ((n = fis.read(buf)) != -1) {
            dos.write(buf, 0, n);
            System.out.println(n);
            dos.flush();
        }
        //should i close the dataoutputstream here and make a new one each time?                 
        dos.write(done, 0, 3);
        dos.flush();
    }
    //or is this good?
    dos.close();
    

    收到

    for (int i = 0; i < files.size(); i++) {
        System.out.println("Receiving file: " + files.get(i).getName());
        //create a new fileoutputstream for each new file
        fos = new FileOutputStream("C:\\users\\tom5\\desktop\\salestools\\" + files.get(i).getName());
        //read file
        while ((n = dis.read(buf)) != -1 && n != 3) {
            fos.write(buf, 0, n);
            fos.flush();
        }
        fos.close();
    }
    
  • @FadlyDzil 这不是编码服务。我已经提供了所有必要的代码。我希望任何有能力的程序员都能将我的其他评论转化为可用的代码。

  • @Tom Math.min() 用于正确处理最后一个缓冲区。您不能假设文件大小是缓冲区长度的倍数。

  • 这很完美,我对 n = dis.read(buf,0,Math.min) 部分感到困惑,math.min 是否确定文件大小是否小于缓冲区大小?如果是这样,它只会用 file.length 部分填充缓冲区?

  • 引用 12

    您正在读取套接字,直到 read() 返回 -1。这是流结束条件 (EOS)。当对等方关闭连接时会发生 EOS。而不是在完成写入一个文件时。

    您需要在每个文件之前发送文件大小。您已经对文件数量做了类似的事情。然后确保您读取了该文件的确切字节数:

    String filename = dis.readUTF();
    long fileSize = dis.readLong();
    FileOutputStream fos = new FileOutputStream(filename);
    while (fileSize > 0 && (n = dis.read(buf, 0, (int)Math.min(buf.length, fileSize))) != -1)
    {
      fos.write(buf,0,n);
      fileSize -= n;
    }
    fos.close();
    

    您可以将所有这些内容放在一个循环中,该循环在 readUTF() throws EOFException 。相反,当然,您必须 writeUTF(filename) 在发送数据之前在发送方 writeLong(filesize) and

  • 引用 13

    另一个选择是将每个文件的大小以及文件名写入“标头”。然后您的服务器端代码就可以知道何时停止写入每个文件并开始写入下一个文件。

  • 尝试自学 Java,只是做了一些简单的项目来第一次玩 io。我感觉我的 dos.write(buf,0,n) 及其接收伙伴只是在不断读取和写入,因此所有数据都被写入了第一个文件?当第一个文件已完全写入时,我是否需要添加一个控件来发出信号?

返回
作者最近主题: