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

huangapple go评论73阅读模式
英文:

File corrupted while sending through socket

问题

以下是已翻译的内容:

我只是在尝试从套接字发送一些文件,我能够在没有任何中断的情况下发送这些文件:无论文件大小是小还是大,都没有关系,它都能顺利发送。

但我遇到的问题是,我发送的文件被损坏了,即它无法像音频或视频那样播放。我已经阅读了这个链接,但没有帮助。

我使用的代码如下。

服务器端:

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) {
    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) {
    e.printStackTrace();
} finally {
    if (in != null) {
        in.close();
    }
}

提前致谢。

英文:

I am just trying to send some files from a socket and i am able to send those files without any interruption: also whether the size file is small or large that does not matter it sends like a charm.

But the problem in my case that is arising is the file that i sent is being corrupted, i.e. it is not playing like audio or video. I have already gone through this but it did not helped.

The code that I am using is below.

Server Side:

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();
            }
        }

And the Client Side :

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();
                }

            }

Thanks in advance.

答案1

得分: 1

所以在评论中的交谈之后,正如@MarquisofLorne所说,要从我的服务器端代码中删除我写的那行代码。即从服务器端代码中删除这行代码:

dos.writeLong(mybytearray.length);

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

long sizeOfFile = clientData.readLong();

这解决了这个问题。

英文:

So after the conversations in comments and as @MarquisofLorne told to delete the line that i have written in my server side code. i.e either delete this line from server side code:

dos.writeLong(mybytearray.length);

or write this below line code in client side code:

long sizeOfFile = clientData.readLong();

It solves the problem.

答案2

得分: -1

服务器端

你的代码发送了缓冲区长度(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(); // 读取 F 字节的文件名
    
    // 缺少 readLong(..) 8 字节
    // long fileLen = clientData.readLong(); <= 在读取内容之前读取文件长度
    
    // 读取 N 字节,但是前面的 8 字节是文件长度,应该先将其写入文件。
    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 时,它无法从流中读取内容,而不是流的结尾。

英文:

Server Side

Your code sends buffer length(4096), which is a bug.

It should send file length.

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

}

Client Side

Server sends two meta data

  • file name( F bytes, encoded by utf-8)
  • file length (8 bytes)

And then sends entire contents( N bytes)

But client code ignores file length(8bytes), just reads file name and contents N bytes

    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);
    }

Don't rely on -1

Your codes keep relying on -1 in while loop

  while ((read = dis.read(mybytearray)) != -1) {
    dos.write(mybytearray, 0, read);
  }

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

-1 means abnormal state.

Because server knows the exact size of a file and writes out the file, client should read the exact length of bytes from stream.

If server send 1234 bytes, when client read -1 from clientData.read(..), it fails to read contents from stream, not end of stream.

huangapple
  • 本文由 发表于 2020年8月24日 11:49:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/63554480.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定