gpt4 book ai didi

Java-通过套接字发送文件时文件会损坏,但发送到本地主机时除外

转载 作者:塔克拉玛干 更新时间:2023-11-02 08:06:09 25 4
gpt4 key购买 nike

我正在尝试使用套接字在 Java 中构建文件服务器和文件客户端程序,并且在尝试将文件从服务器发送到客户端时遇到了一些问题。下面是我分别用来发送和接收文件的代码:

private void sendFile(String filePath) {
try (BufferedInputStream fileInputStream = new BufferedInputStream(new FileInputStream(filePath))) {
BufferedOutputStream outputStream = new BufferedOutputStream(socket.getOutputStream());
byte[] buffer = new byte[4096];
while (fileInputStream.read(buffer) != -1) {
outputStream.write(buffer);
outputStream.flush();
}
}
catch (IOException e) {e.printStackTrace();}
}

private void downloadFile(String fileName, long fileSize) {
try (BufferedOutputStream fileOutputStream = new BufferedOutputStream(new FileOutputStream(downloadDir + "/" + fileName));
BufferedInputStream inputStream = new BufferedInputStream(socket.getInputStream());
OutputStreamWriter writer = new OutputStreamWriter(new BufferedOutputStream(socket.getOutputStream()), "UTF-8");) {
writer.write("GET" + fileName + System.lineSeparator());
writer.flush();
long totalReceived = 0;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
while (totalReceived < fileSize) {
inputStream.read(buffer);
int numOfBytesToWrite = fileSize - totalReceived > bufferSize ? buffer.length : (int)(fileSize % bufferSize);
fileOutputStream.write(buffer, 0, numOfBytesToWrite);
fileOutputStream.flush();
totalReceived += numOfBytesToWrite;
}
}
catch (IOException e) {}
}

下载的文件确实已创建并且似乎大小合适,但总是损坏并且无法被任何程序打开。但是,当我在同一台机器上运行客户端并将其连接到“localhost”或“127.0.0.1”时,这个问题并没有出现,那么就没有问题,下载的文件也没有损坏。看到我的代码有任何问题吗?

最佳答案

在您的 sendFile() 中,您需要考虑 read() 的返回值,它可能小于 4096...然后应该在 write 调用中使用该值,以仅写出数组中具有已填充...

int bytesRead = 0;
while ((bytesRead = fileInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
outputStream.flush();
}

类似的问题出现在downloadFile()中,read()返回的是实际读取的字节数,有些值小于等于4096...

long totalReceived = 0;
int bufferSize = 4096;
byte[] buffer = new byte[bufferSize];
while (totalReceived < fileSize) {
int bytesRead = inputStream.read(buffer);
fileOutputStream.write(buffer, 0, bytesRead);
fileOutputStream.flush();
totalReceived += bytesRead;
}

为什么您的代码可以在本地主机上运行,​​但不能通过网络运行?

  • 网络的典型物理层是以太网,其 MTU 为 1500 字节。因此,您可能会看到连续的 read() 调用只填充了 1500 或更少字节的缓冲区...

  • 然而,本地主机在堆栈中进行了优化,以绕过物理层,不会有此限制。在这种情况下,除非您的文件大小恰好是 4096 的倍数,否则连续调用很可能会填满整个 4096 缓冲区,除了最后一个。

关于Java-通过套接字发送文件时文件会损坏,但发送到本地主机时除外,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36754356/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com