【问题标题】:How to tranfer large file from server to client using udp如何使用udp将大文件从服务器传输到客户端
【发布时间】:2015-10-08 06:25:16
【问题描述】:

我想做一个关于java的项目。我的目标是使用 UDP 将大文件从服务器传输到客户端。我发现 UDP 不支持大于 84kb 的数据?那么如何做到这一点..?有什么办法吗?

【问题讨论】:

  • 通过Java对象序列化
  • 感谢 Hanzallah Afgan,你能说得更具体一些吗?我对这个有点陌生..
  • 是的。我给你举个例子。
  • UDP 不保证数据包的传递……有了文件,你最终会得到不完整的东西。
  • 感谢 Scartag 和 Hanzallah Afgan

标签: java udp file-transfer


【解决方案1】:

用于传输文件的 TCP/IP 客户端和服务器程序。服务器发送文件,客户端接收文件。 对于文件传输,您应该使用 TCP(传输控制协议),它是面向连接的协议,可确保在另一端成功传输数据,而对于实时流,我们使用 UDP(用户数据报协议),它是无确认的无连接协议是在两者之间进行的。 您应该通过 TCP 而不是 UDP 来执行此操作。

在 UDP 中,64 KB 是一个完整 IP 数据报包的理论最大大小。

请参阅java socket programming 以获得更好的理解。

服务器

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFileChooser;

public class Server {

    private ServerSocket sSocket;
    private Socket socket;
    private DataOutputStream dos;
    private OutputStream os;
    private File file;
    private JFileChooser jfc = new JFileChooser();

    public Server() throws IOException {

        sSocket = new ServerSocket(1234);
        System.out.println("Waiting for incoming connection request...");
        socket = sSocket.accept();
        jfc.showOpenDialog(null);
        file = jfc.getSelectedFile();
        FileInputStream fis = new FileInputStream(file);
        os = socket.getOutputStream();
        dos = new DataOutputStream(os);
        dos.writeUTF(file.getName());
        int count = 0;
        byte[] b = new byte[1000];
        System.out.println("Uploading File...");
        while ((count = fis.read(b)) != -1) {
           dos.write(b, 0, count);
        }

        fis.close();
        socket.close();
        System.out.println("File Transfer Completed Successfully!");
    }

    public static void main(String[] args) throws Exception {
        new Server();
    }

}

客户

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JFileChooser;

public class Client{

    private Socket socket;
    private DataInputStream dis;
    private InputStream is;
    private File file;
    private JFileChooser jfc = new JFileChooser();

    public Client() throws Exception {
        socket = new Socket("localhost", 1234);
        is = socket.getInputStream();
        dis = new DataInputStream(is);
        System.out.println("Waiting for File");
        jfc.setSelectedFile(new File(dis.readUTF()));
        jfc.showSaveDialog(null);
        file = jfc.getSelectedFile();
        FileOutputStream fos = new FileOutputStream(file);
        int count = 0;
        byte[] b = new byte[1000];
        System.out.println("Incoming File");
        while((count = dis.read(b)) != -1){
            fos.write(b, 0, count);
        }

        fos.close();
        socket.close();
        System.out.println("File Transfer Completed Successfully!");
    }

    public static void main(String[] args) throws Exception{
        new Client();
    }

}

【讨论】:

  • Hum... Socket 和 ServerSocket 是 TCP API。通过 UPD 协议传输,必须使用 DatagramSocket 和 DatagramPacket。
  • 是的,我很清楚。我已经提到过。
  • @LittleSanti 请参阅答案的第一行。
  • 这是错误的答案。你甚至不具备基本的逻辑。你应该明白规范是谁定义的(如果UDP不适合,并不意味着必须使用TCP)。除非有人准备好接受它,否则您不应该提供 TCP 解决方案。其次,以太网不支持 100k 数据包这一事实并不意味着我们应该使用替代介质来传输更长的文件。 UDP 应该能够满足规范。
  • @RecognizeEvilasWaste 我不知道你是什么人?我让你给他答案而不是给我。你不明白我在答案的描述中写了什么。请不要再使用 cmets。帮助他。
【解决方案2】:

如果这是出于任何实际目的,您应该使用 TCP。但是,如果是为了学习,这将是一个非常有趣的练习:您基本上需要重新实现 TCP 在 IP 之上提供的功能,所以我建议您先阅读一下。总结如下:

TCP 的工作原理是将数据分解成适合单个 IP 数据包的较小块。由于 IP 数据包可能会在途中重新排序,而有些可能根本不会出现,因此每个数据包都有一个序列号,允许接收者将它们重新组合成正确的顺序。接收者还必须确认每个收到的数据包;如果发送方在一定时间内没有收到数据包 x 的确认,它将重新发送数据包 x(并保持定期发送直到它被确认)。这意味着收件人还必须准备好接收同一数据包的多个副本。

因此,在您的情况下,您需要确定 UDP 数据报的某种格式:例如,前 8 个字节可能包含发送方为文件选择的随机标识符(这样不同的文件可以同时传输而无需数据报混淆),接下来的四个字节将是序列号,数据包的其余部分将是实际文件数据的一块。也许第一个数据包也应该包含文件名,以及文件包含的数据报总数。一个确认数据报只需要包含标识符和序列号。

【讨论】:

    【解决方案3】:

    我会尝试一个简单的 API,例如 tftp。据称,TFTP 依赖于 UDP。

    【讨论】:

    • “据称”?不难查。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-09
    • 2020-01-01
    • 1970-01-01
    相关资源
    最近更新 更多