I'm trying to send a file from a client to a server with Sockets in Java. It works fine when I am testing on the same machine, but when I test across different machines, I lose large chunks of data, resulting in a corrupted file. If I try to send a very small file (<20 bytes), it doesn't even reach the println inside the server's while loop.
Here is my code:
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());
}
}
Client.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();
}
}
}
}
}
I've been working on this for hours and I have made almost no progress. I thought I had a pretty good understanding of how reading/writing from streams works, but clearly I'm missing something here.
Again, everything works perfectly when I am sending and receiving from the same machine. But if I try to send a file between two computers, even if the two are on the same LAN, I lose a lot of the data that was sent.
Can anybody figure out my problem? I've already tried everything I could think of.