关于使用UDP从客户端上传mp3文件到服务器

About uploading mp3 files from clients to the server using UDP

我是 Whosebug 的新手,如果我的问题被不恰当地提出或混淆,请告诉我,谢谢!

我正在做一个音频流项目,允许客户端将他们的 mp3 文件上传到服务器。服务器会将它们存储到一个播放列表中,并将歌曲流式传输回所有客户端。 这是我的客户端上传 mp3 的代码:

    public static void sendPackets(){
        System.out.println("Sending test file...");
        try{
            while (active){
                //The song needs to be uploaded;
                File file = new File("Sorrow.mp3") 
                FileInputStream fis = new FileInputStream(file);
                byte[] byteStream = new byte[(int) file.length()]; 
                //Trying to convert mp3 to byteStream
                fis.close();
                InetAddress destination = InetAddress.getByName("localhost");
                DatagramPacket sendingAirMail = new DatagramPacket(byteStream, byteStream.length, destination, 50010); // 50010 is the listening port
                serverSocket.send(sendingAirMail); // sending the entire bytestream via UDP
                // ServerSocket is a DatagramSocket
                break;
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

问题出在这里:

serverSocket.send(sendingAirMail);

因为它会给我这个错误:

java.net.SocketException: The message is larger than the maximum supported by the underlying transport: Datagram send failed
    at java.base/java.net.DualStackPlainDatagramSocketImpl.socketSend(Native Method)
    at java.base/java.net.DualStackPlainDatagramSocketImpl.send(DualStackPlainDatagramSocketImpl.java:136)
    at java.base/java.net.DatagramSocket.send(DatagramSocket.java:695)
    at client.sendPackets(client.java:116)
    at client.run(client.java:67)

查了下google,得知是因为UDP每次发送的包都有大小限制,所以想知道这种情况下UDP包如何正确分离?我知道在这种情况下 TCP 会更好,但我认为无论如何我都需要学习如何分离包,因为我需要使用 UDP 从服务器流回字节数组。任何帮助将不胜感激!

如果需要,我可以 post 我的服务器和其他客户端信息。

问题是您需要将您的文件分成几部分并提交。对于 UDP,您需要一些东西来确保文件的完整性和正确性。以下是一些建议:

首先,你需要切割你的文件,所以你需要在头部给出一个seq标志。此外,您可能需要一些额外的信息,例如文件的总大小、时间戳等。

struct msg {
    int seq;
    int total_seq;
    int size;
    void *data;
};

然后,最好建立一个发送缓冲区和接收缓冲区,每次检查缓冲区是否为空,如果没有,send/receive它。

收到一些片段后,您需要使用 seq 标志重建它们。当某些seq丢失时,您需要重传。所以这里需要一个重传设计。

总之,你至少需要具备以下条件:

  1. 一个用户定义的head前信息
  2. cut/rebuild 文件
  3. 重传(GBN 或 FEC 或两者)

希望对您有所帮助。