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

问题描述

我只是想从套接字发送一些文件,并且能够无中断地发送这些文件:还有大小文件的大小无关紧要,就像附件一样发送。

但是在我的情况下出现的问题是我发送的文件已损坏,即,它不能像音频或视频那样播放。我已经经历过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,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,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个字节)

但是客户端代码忽略文件长度(8bytes),仅读取文件名和内容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,read);
    }

不要依赖-1

您的代码继续依靠-1循环中的while

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

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

-1表示异常状态。

由于服务器知道文件的确切大小并写出文件,因此客户端应从流中读取字节的确切长度。

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

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...