通过套接字发送时文件损坏

File corrupted while sending through socket

我只是想从一个套接字发送一些文件,我能够在没有任何中断的情况下发送这些文件:无论大小文件是小还是大,这都没有关系,它就像一个魅力一样发送。

但我遇到的问题是我发送的文件已损坏,即无法像音频或视频那样播放。我已经完成 this 但没有帮助。

我使用的代码如下。

服务器端:

File file = new File(
                Environment.getExternalStorageDirectory(),
                "testingFile.mp4");
        byte[] mybytearray = new byte[4096];
        FileInputStream fis = null;
        try {
            fis = new FileInputStream(file);
        } catch (FileNotFoundException ex) {
            ex.printStackTrace();
        }
        BufferedInputStream bis = new BufferedInputStream(fis);
        DataInputStream dis = new DataInputStream(bis);
        OutputStream os;
        DataOutputStream dos = null;
        try {
            os = socket.getOutputStream();
            dos = new DataOutputStream(os);
            dos.writeUTF(file.getName());
            dos.writeLong(mybytearray.length);
            int read;
            while ((read = dis.read(mybytearray)) != -1) {
                dos.write(mybytearray, 0, read);
            }
            socket.close();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } finally {
            try {
                if (dos != null) {
                    dos.flush();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

和客户端:

File file = new File(
                    Environment.getExternalStorageDirectory(),
                    "TEST SUCCESS.mp4");
            InputStream in = null;
            int bufferSize;

            try {
                bufferSize = socket.getReceiveBufferSize();
                in = socket.getInputStream();
                DataInputStream clientData = new DataInputStream(in);
                String fileName = clientData.readUTF();
                System.out.println(fileName);
                OutputStream output = new FileOutputStream(
                        file);
                byte[] buffer = new byte[bufferSize];
                int read;
                while ((read = clientData.read(buffer)) != -1) {
                    output.write(buffer, 0, read);
                }
                output.flush();
                socket.close();

            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } finally {
                if (in != null) {
                    in.close();
                }

            }

提前致谢。

所以在评论中的对话之后,@MarquisofLorne 告诉我删除我在服务器端代码中编写的行。即从服务器端代码中删除此行:

dos.writeLong(mybytearray.length);

或者在客户端代码中写下这行代码:

long sizeOfFile = clientData.readLong();

它解决了问题。

服务器端

您的代码发送缓冲区长度 (4096),这是一个错误。

它应该发送文件长度。

File file = new File( ... );
try {
    //dos.writeLong(mybytearray.length);
    dos.writeLong(file.length());

}

客户端

服务器发送两个元数据

  • 文件名(F字节,utf-8编码)
  • 文件长度(8 字节)

然后发送全部内容(N字节)

但是客户端代码忽略文件长度(8字节),只读取文件名和内容N字节

    in = socket.getInputStream();
    DataInputStream clientData = new DataInputStream(in);

    String fileName = clientData.readUTF(); // ok read F bytes
    
    // missing readLong(..) 8 bytes
    // long fileLen = clientData.readLong(); <= read file length before reading contents
    
    // read N bytes, but first 8 bytes are file length, which are written into file.
    int read;
    while ((read = clientData.read(buffer)) != -1) {
        output.write(buffer, 0, read);
    }

不要依赖-1

您的代码在 while 循环

中继续依赖 -1
  while ((read = dis.read(mybytearray)) != -1) {
    dos.write(mybytearray, 0, read);
  }

  while ((read = clientData.read(buffer)) != -1) {
    output.write(buffer, 0, read);
  }

-1表示异常状态

因为服务器知道文件的确切大小并写出文件,所以客户端应该从流中读取准确的字节长度。

如果服务器发送 1234 字节,当客户端从 clientData.read(..) 读取 -1 时,它无法从流中读取内容,而不是流的结尾。