我正在尝试使用套接字在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”时,此问题不会显示,然后没有问题,下载的文件也没有损坏。查看我的代码的任何问题?
答案 0 :(得分:4)
在你的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;
}
为什么您的代码可以在localhost上运行,但不能通过网络运行?
网络的非典型物理层是以太网,其MTU为1500字节。所以你可能会看到连续的read()调用只填充1500或更少的缓冲区字节......
但是,在堆栈中优化localhost以绕过不具有此限制的物理层。在这种情况下,除了文件大小是4096的完全倍数之外,连续调用可能会填充整个4096缓冲区,除非你的文件大小是4096的完全倍数。