I am trying to create a very barebones fileserver that does nothing more than download a zip file and exit, but I am running into problems. I have two main problems.
The first is that when I test on localhost, it sort of works, in that it transfers the zip file, but when I try to open it, I get an error about it being corrupt. It may be something to do with the zip file format, or how I am transferring it.
The second problem is that it fails whenever I use anything but localhost. I have tried a website redirect to my IP, and just putting in my ip address, and both fail, even when I turn off all firewalls and antivirus.
Server code:
import java.io.*;
import java.net.*;
public class FileServer {
public static void main(String[] args) throws IOException {
final int PORT_NUMBER = 44444;
ServerSocket serverSock = null;
PrintWriter out = null;
BufferedInputStream bin = null;
OutputStream os = null;
Socket clientSock = null;
File file;
byte[] fileData;
String filename = "file.zip";
while(true) {
try {
//Listen on port
serverSock = new ServerSocket(PORT_NUMBER);
//Get connection
clientSock = serverSock.accept();
System.out.println("Connected client");
//Get output stream
out = new PrintWriter(clientSock.getOutputStream(), true);
out.println(filename); //Print filename
file = new File(filename); //Get file
fileData = new byte[(int)file.length()]; //Stores the file data
bin = new BufferedInputStream(new FileInputStream(file));
out.println((int)file.length()); //Print filesize
bin.read(fileData); //Read contents of file
os = clientSock.getOutputStream();
os.write(fileData); //Write the file data
os.flush();
} catch(SocketException e) {
System.out.println("Client disconnected");
} catch(Exception e) {
System.out.println(e.getMessage());
System.exit(1);
} finally {
//Close all connections
System.out.println("Shutting down");
if(os != null) {
os.close();
}
if(bin != null) {
bin.close();
}
if(out != null) {
out.close();
}
if(clientSock != null) {
clientSock.close();
}
if(serverSock != null) {
serverSock.close();
}
}
}
}
}
Client code snippet, assume that all syntax is correct and everything else exists and works, because I probably mismatched some braces or something when I cut the snippet out.
import java.io.*;
import java.net.*;
import javax.swing.JOptionPane;
public static void main(String[] args) {
final int PORT_NUMBER = 44444;
final String HOSTNAME = "127.0.0.1";
String filename = "default.txt";
Socket sock = null;
BufferedReader in = null;
BufferedOutputStream bos = null;
InputStream is = null;
byte[] fileData;
//Attempt to connect
try {
sock = new Socket(HOSTNAME, PORT_NUMBER);
in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
is = sock.getInputStream();
} catch(UnknownHostException e) {
JOptionPane.showMessageDialog(this, "Error: could not connect to host " + HOSTNAME + " on port number " + PORT_NUMBER);
System.exit(1);
} catch(ConnectException e) {
JOptionPane.showMessageDialog(this, "Error: connection refused");
System.exit(1);
} catch(Exception e) {
JOptionPane.showMessageDialog(this, e);
System.exit(1);
}
try {
filename = in.readLine();
bos = new BufferedOutputStream(new FileOutputStream(filename));
fileData = new byte[Integer.decode(in.readLine())]; //Gets file size
is.read(fileData);
bos.write(fileData);
bos.flush();
bos.close();
if(is != null) {
is.close();
}
if(in != null) {
in.close();
}
if(bos != null) {
bos.close();
}
if(sock != null) {
sock.close();
}
} catch(Exception e) {
JOptionPane.showMessageDialog(this, e);
System.exit(1);
}
JOptionPane.showMessageDialog(this, "Download complete");
}
}
}
}
EDIT: It works just fine on localhost with .doc and .docx files, it is only .zip that causes problems.
I see two problems on your client, which may cause problems:
You are using a
BufferedReader
to read the first line, and then access the plain underlying InputStream from the socket withis.read(fileData);
First, the BufferedReader (and it's InputStreamReader) may read more than only the first line on
readLine()
- the rest is buffered for later retrieval, but you don't read anything more. So you may be missing the start of your file.Second, you have only one main
read
for your socket-InputStream, which may or may not fill the whole array, since you don't check the result of this method call. Thus the end of the file may be consisting of zero-bytes instead of the real data (and certainly there will be as much zero bytes as you missed for the first problem). You should instead read (and then maybe instantly write to the file) in a loop, checking (and adding) the results of the read call.Edit: For reading only into the array:
There is a
readFully()
method inDataInputStream
which does just this, I think. If you have bigger files, you would not want it completely in one array, but read and write alternately (using a smaller array as a buffer):I can only speculate why it works with doc - did you really compare the output files? Maybe your Word documents are smaller then your zip file, and thus the second problem did not really apply, since all the file could be read in one step.
The same (second) problem actually applies to your server for reading the file, too.
You may think about using a
DataInputStream
(and DataOutputStream at the server side) - it allows reading Strings too, without needing a Writer (and additional Buffering).