【问题标题】:Socket file transfer套接字文件传输
【发布时间】:2011-08-14 20:43:49
【问题描述】:

在这个code 中,如果文件是第一次发送的(无论我发送多少个文件),代码都可以正常工作。但是当我把FileSender放在一个循环中逐个发送文件时,第一次传输后,接收端接收到的数据是任意的(如果在调试过程中检查),它甚至不会接收到文件。这是我所做的更改,但它不起作用。

FileSender.java

import java.io.OutputStream;
import java.io.File;
import java.net.Socket;
public class FileSender {
public  void main(Socket socket,String[] args) {
try {

  OutputStream os     = socket.getOutputStream();
  int cnt_files = args.length;

  // How many files?
  ByteStream.toStream(os, cnt_files);

  for (int cur_file=0; cur_file<cnt_files; cur_file++) {
    ByteStream.toStream(os, new File(args[cur_file]).getName());
    ByteStream.toStream(os, new File(args[cur_file]));
  }
}
catch (Exception ex) {
  ex.printStackTrace();
}
}
}

String[] args 包含要传输的文件的路径。

FileReceiver.java

import java.io.File;
import java.io.InputStream;
import java.net.Socket;

public class FileReceiver {

public void main(Socket socket,String arg) {
try {
    InputStream in = socket.getInputStream();

  int nof_files = ByteStream.toInt(in);
System.out.println("reach 1     "+ nof_files);
  for (int cur_file=0;cur_file < nof_files; cur_file++) {
    String file_name = ByteStream.toString(in);

    File file=new File(arg+file_name);
    System.out.println("Received path is :  "+file);
    ByteStream.toFile(in, file);
  }

}
catch (java.lang.Exception ex) {
  ex.printStackTrace(System.out);
}
}

}

arg 包含要存储文件的路径。

我希望在我想传输文件时调用提到的 ma​​in 函数。基本上我想传输多个文件,这些文件也可以包含目录。为此,我编写了以下代码。

ServerFile.java

import java.io.*;
import java.net.*;
public class ClientFile implements Runnable{
Socket clientsocket;
public void run() {
    try
    {
        clientsocket = new Socket("219.64.189.14",6789);
    // Some code
    copy(outtoserver,infromserver, files);      // files contains the path of files to be transferred.
    // Some code
        clientsocket.close();
    }
    catch(Exception e2)
    {
            System.out.println("ClientFile   "+String.valueOf(e2) + "\n");
    }
}
public void copy(DataOutputStream outtoserver,BufferedReader infromserver,String[] files)
{
    try
    {
        FileSender fs = new FileSender();
        int totalfiles=0;
        int r=0;
        File oldfile;
        outtoserver.write(files.length);
        String chk;
        while(totalfiles<files.length)
        {

            oldfile = new File(files[totalfiles]);
            if(oldfile.isDirectory())
            {
                outtoserver.writeBytes("folder\n");
                File folder1[] = oldfile.listFiles();
                String[] folder = new String[folder1.length];
                int count=0;
                for(File name : folder1)
                {
                    folder[count] = name + "";
                    System.out.println(folder[count]);
                    count++;
                }
                outtoserver.writeBytes(oldfile.getName()+"\n");
                fs.main(clientsocket, folder);

            }
            else if(oldfile.isFile())
            {
                outtoserver.writeBytes("file\n");
        chk = infromserver.readLine();
                if(chk.equals("send"))
                {
                    outtoserver.writeBytes(oldfile.getName()+"\n");
                    String[] folder = new String[]{oldfile.getAbsolutePath()};
                    fs.main(clientsocket, folder);
                }
                totalfiles++;
                outtoserver.flush();

            }
        }
    }
    catch(Exception e)
    {
        System.out.println("ClientFile -->>  "+e.toString());
    }
}
}

ClientFile.java

import java.io.*;
import java.net.*;
import javax.swing.*;
class ServerFile implements Runnable {
Socket conn;
public ServerFile(Socket a)
{
    conn = a;
}
public void run() {
    File file1;
    String clientsen="";
    try
    {  // Some code
       copy(outtoclient,infromclient,file1.getAbsolutePath());      //file1 is the directory to which the file has to stored.    
   // some code
    }      
    catch(Exception e0)
    {
         System.out.println("ServerFile   "+String.valueOf(e0)+"\n"+e0.getCause());
    }
}//end main
public void copy(DataOutputStream outtoclient,BufferedReader infromclient,String basepath)
{
    try
    {
         FileReceiver fr = new FileReceiver();
         int totfiles = infromclient.read();
         int tot=0;
         File file;
         String path = null,chk;
         while(tot<totfiles)
         {
             chk = infromclient.readLine();
             if(chk.equals("file"))
             {
                outtoclient.writeBytes("send\n");
                path = infromclient.readLine();
                path = basepath+File.separator+path;
                file=new File(path);
                fr.main(conn, basepath+File.separator);
             }
             else if(chk.equals("folder"))
             {
                 String name = infromclient.readLine();
                 name = basepath+File.separator+name;
                 new File(name).mkdir();
                 fr.main(conn, name+File.separator);
             }
             tot++;
         }
    }
    catch(Exception e)
    {
        System.out.println("Server file:    "+e.toString());
    }
}

}//end class

如果我错了,一定要纠正我。

任何帮助表示赞赏。

【问题讨论】:

  • ServerFile.javaClientFile.java 甚至都不编译。他们的run() 方法引用来自其他方法的变量(outtoserverinfromserverfilesouttoclientinfromclient)。您正在编译的实际代码是什么?

标签: java sockets file-transfer


【解决方案1】:

您将"file\n""folder\n" 发送给客户端。要读取这些字符串,您使用的是BufferedReader。请密切注意该类的名称:BufferedReader。当您在BufferedReader 上调用readLine() 时,它会缓冲(读取)至少 尽可能多的字节以读取该行。它可能读取更多,而不是读取该行所需的确切字节数。例如,假设BufferedReader 的缓冲区大小为 256,但您的行(包括"\n")只需要 8 个字节。这意味着FileReceiver 不会读取剩余的 248 个缓冲字节。然后它会被彻底弄糊涂,因为它需要一个 4 字节的整数,但它实际上正在读取其他内容。

我建议您利用示例中已经使用的技术。例如,发送"file" 使用:

ByteStream.toStream(os, "file")

并使用以下方式阅读:

ByteStream.toString(in)

【讨论】:

    【解决方案2】:

    所以,我真的不明白它是如何将文件内容与文件名分开的?可能更好地创建包含文件名和内容的可序列化类。在这种情况下,您可以使用 ObjectInput/OutputStream。否则,您需要定义一些文件内容/文件名分隔符并使用 Scanner 类将文件与输入流分开。

    【讨论】:

    • 文件名总是在文件内容之前发送。它看起来像这样:[length of file name bytes (4-byte integer)][file name bytes][length of file content bytes (4-byte integer)][file content bytes]。对于这种特殊情况,Serializable 类听起来有点矫枉过正。
    • @Audrey:对不起,我在看FileSenderFileReceiver。至少可以说,其他类看起来不同......
    • @Adam 至于我 pankaj 应该使用一些块分隔符或使用可序列化。否则很难保证他的模式稳定工作。我认为 Serializable 足以制作一些传输数据包。
    猜你喜欢
    • 2011-10-13
    • 1970-01-01
    • 2015-03-06
    • 2015-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多