Я пытаюсь отправить файл с клиента на сервер с сокетами в Java. Он отлично работает, когда я тестирую на одной машине, но когда я тестирую на разных машинах, я теряю большие куски данных, что приводит к повреждению файла. Если я попытаюсь отправить очень маленький файл (‹20 байт), он даже не достигнет println внутри цикла while сервера.
Вот мой код:
Server.java
package edu.mst.cs.sensorreceiver;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
private static final int PORT = 51111;
private static final int CHUNK_SIZE = 1024;
private static final File _downloadDir = new File("downloads/");
public static void main(String[] args) {
if (!_downloadDir.exists()) {
if (!_downloadDir.mkdirs()) {
System.err.println("Error: Could not create download directory");
}
}
Socket socket = null;
try {
ServerSocket server = new ServerSocket(PORT);
while (true) {
System.out.println("Waiting for connection...");
socket = server.accept();
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
String name = in.readLine();
File file = new File(_downloadDir, name);
String size = in.readLine();
int fileSize;
try {
fileSize = Integer.parseInt(size);
} catch (NumberFormatException e) {
System.err.println("Error: Malformed file size:" + size);
e.printStackTrace();
return;
}
System.out.println("Saving " + file + " from user... (" + fileSize + " bytes)");
saveFile(file, socket.getInputStream());
System.out.println("Finished downloading " + file + " from user.");
if (file.length() != fileSize) {
System.err.println("Error: file incomplete");
}
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void saveFile(File file, InputStream inStream) {
FileOutputStream fileOut = null;
try {
fileOut = new FileOutputStream(file);
byte[] buffer = new byte[CHUNK_SIZE];
int bytesRead;
int pos = 0;
while ((bytesRead = inStream.read(buffer, 0, CHUNK_SIZE)) >= 0) {
pos += bytesRead;
System.out.println(pos + " bytes (" + bytesRead + " bytes read)");
fileOut.write(buffer, 0, bytesRead);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (fileOut != null) {
try {
fileOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
System.out.println("Finished, filesize = " + file.length());
}
}
Клиент.java
package edu.mst.cs.sensorreceiver;
import java.io.*;
import java.net.Socket;
public class Client {
private static final String HOSTNAME = "131.151.163.153";
private static final int PORT = 51111;
private static final int CHUNK_SIZE = 1024;
public static void main(String[] args) {
sendFile(args[0]);
}
private static void sendFile(String path) {
if (path == null) {
throw new NullPointerException("Path is null");
}
File file = new File(path);
Socket socket = null;
try {
System.out.println("Connecting to server...");
socket = new Socket(HOSTNAME, PORT);
System.out.println("Connected to server at " + socket.getInetAddress());
PrintStream out = new PrintStream(socket.getOutputStream(), true);
out.println(file.getName());
out.println(file.length());
System.out.println("Sending " + file.getName() + " (" + file.length() + " bytes) to server...");
writeFile(file, socket.getOutputStream());
System.out.println("Finished sending " + file.getName() + " to server");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (socket != null) {
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
private static void writeFile(File file, OutputStream outStream) {
FileInputStream reader = null;
try {
reader = new FileInputStream(file);
byte[] buffer = new byte[CHUNK_SIZE];
int pos = 0;
int bytesRead;
while ((bytesRead = reader.read(buffer, 0, CHUNK_SIZE)) >= 0) {
outStream.write(buffer, 0, bytesRead);
outStream.flush();
pos += bytesRead;
System.out.println(pos + " bytes (" + bytesRead + " bytes read)");
}
} catch (IndexOutOfBoundsException e) {
System.err.println("Error while reading file");
e.printStackTrace();
} catch (IOException e) {
System.err.println("Error while writing " + file.toString() + " to output stream");
e.printStackTrace();
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
Я работал над этим часами и почти не продвинулся. Я думал, что довольно хорошо понимаю, как работает чтение/запись из потоков, но явно что-то здесь упускаю.
Опять же, все работает отлично, когда я отправляю и получаю с одной и той же машины. Но если я попытаюсь отправить файл между двумя компьютерами, даже если они находятся в одной локальной сети, я потеряю большую часть отправленных данных.
Может ли кто-нибудь понять мою проблему? Я уже перепробовал все, что мог придумать.