英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论