I have implemented a client-server communication in java. The following are the codes for transferring a set of files :
Server code:
public class TransferServer {
static List<String> filesListInDir = new ArrayList<String>();
static String zipName = "tmp.tar.gz";
public static void main(String[] args) throws IOException, InterruptedException {
// TODO Auto-generated method stub
ServerSocket s1 = new ServerSocket(7104);
System.out.println("Transfer server started");
while (true) {
Socket sckt = s1.accept();
System.out.println("Request received. Please wait..");
zipData();
transferData(sckt);
System.out.println("Data transferred");
}
}
private static void transferData(Socket ts) throws IOException {
FileInputStream fi=new FileInputStream(zipName);
byte b[] = new byte[8000];
fi.read(b, 0, b.length);
OutputStream os = ts.getOutputStream();
os.write(b, 0, b.length);
fi.close();
}
Client code:
public class Fetchmyfile {
static String addr_list="/home/pi/addresslist.txt";
static String zipName = "tmp.tar.gz";
public static void main(String[] args) throws InterruptedException, IOException {
// TODO Auto-generated method stub
trigger();
}
private static void trigger() throws InterruptedException, IOException {
// TODO Auto-generated method stub
String[] hostList = readAddressList(addr_list);
//remove tmp.zip
for (int i = 0; i < hostList.length; i++) {
Runtime r = Runtime.getRuntime();
Process p = null;
try {
p = r.exec("rm /home/pi/combined_data/"+hostList[i]+"/"+zipName);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
p.waitFor();
}
//remove complete
for (int i = 0; i < hostList.length; i++) {
String addr = hostList[i];
TransferClient clientInstance = new TransferClient();
clientInstance.fileCopy(addr, "/home/pi/combined_data/"+addr.trim()+"/tmp.tar.gz");
}
System.out.println("All data has been transferred");
}
private static String[] readAddressList(String addr_list) throws IOException {
FileReader fileReader = new FileReader(addr_list);
BufferedReader bufferedReader = new BufferedReader(fileReader);
List<String> lines = new ArrayList<String>();
String line = null;
while ((line = bufferedReader.readLine()) != null)
{
lines.add(line);
}
bufferedReader.close();
System.out.println("Loaded the host list");
return lines.toArray(new String[lines.size()]);
}
}
public class TransferClient {
public boolean fileCopy(String sensor_node_ip, String filename) throws InterruptedException{
//public static void main(String args[]) throws IOException
{
try {
//String filename = "‎�‎�localfile.zip";
byte b[] = new byte[8000];
Socket s = null;
try {
s = new Socket(sensor_node_ip, 7104);
System.out.println("connection done");
} catch (IOException e) {
System.out.println("Couldn't connect to the server");
return false;
}
InputStream iss = s.getInputStream();
FileOutputStream fr = new FileOutputStream(filename);
iss.read(b, 0, b.length);
fr.write(b, 0, b.length);
fr.close();
s.close();
//unZip(filename);
System.out.println("Tar file recieved from " + sensor_node_ip);
return true;
}
catch (IOException e){
return false;
}
}
}
The problem I am facing is, for a comparatively larger file, the client creates a file of the size of the declared buffer with the expected name. But the file is not readable and being an archived file, cannot be extracted. Whereas, the server actually has the file which is correct by all means. What could be the reason for this. Any suggestions/pointers is highly appreciated.
The problem, as I see it, is you're writing 8000 bytes, regardless of the actual size of the output. You're not even trying to check what size the file might be, so you could be writing garbage if the file is less then 8000 bytes or truncating it if it's over 8000 bytes.
Instead, you should be reading the file till there are no more bytes to be read and ensuring that you're only writing the number bytes which were actual read (as a read might read less than the buffer lengths number of bytes).
This is really basic I/O.
So, the following example strips back the concept to bare bones, focusing only on the transmission of the file between the client and the server. For comparison, I added a MD5 check on each end, so it's easy to compare the file result.
One important aspect of programming is, never assume anything. Always look at what you are been given and make determinations about it at run time (the exception would be if it's documented and agreed upon in advanced, but even then, I'd be double checking, because I trust no one 😉)
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
public class Server {
public static void main(String[] args) {
try (ServerSocket server = new ServerSocket(7104)) {
Socket socket = server.accept();
read(socket);
} catch (IOException ex) {
ex.printStackTrace();
}
}
protected static void read(Socket socket) {
File target = new File("Target.file");
try (InputStream is = socket.getInputStream(); OutputStream os = new FileOutputStream(target)) {
byte bytes[] = new byte[1024];
int bytesRead = -1;
while ((bytesRead = is.read(bytes)) != -1) {
os.write(bytes, 0, bytesRead);
}
System.out.println("Server MD5 = " + Util.getMD5Checksum(target));
} catch (IOException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.security.NoSuchAlgorithmException;
public class Client {
public static void main(String[] args) {
try {
File source = new File(<BYO own file>);
System.out.println("Client MD5 = " + Util.getMD5Checksum(source));
try (Socket socket = new Socket("127.0.0.1", 7104); OutputStream os = socket.getOutputStream(); FileInputStream fis = new FileInputStream(source)) {
byte bytes[] = new byte[1024];
int bytesRead = -1;
while ((bytesRead = fis.read(bytes)) != -1) {
os.write(bytes, 0, bytesRead);
}
} catch (IOException exp) {
}
} catch (IOException | NoSuchAlgorithmException ex) {
ex.printStackTrace();
}
}
}
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class Util {
protected static byte[] createChecksum(File filename) throws IOException, NoSuchAlgorithmException {
try (InputStream fis = new FileInputStream(filename)) {
byte[] buffer = new byte[1024];
MessageDigest complete = MessageDigest.getInstance("MD5");
int numRead;
do {
numRead = fis.read(buffer);
if (numRead > 0) {
complete.update(buffer, 0, numRead);
}
} while (numRead != -1);
return complete.digest();
}
}
// see this How-to for a faster way to convert
// a byte array to a HEX string
public static String getMD5Checksum(File filename) throws IOException, NoSuchAlgorithmException {
byte[] b = createChecksum(filename);
String result = "";
for (int i = 0; i < b.length; i++) {
result += Integer.toString((b[i] & 0xff) + 0x100, 16).substring(1);
}
return result;
}
}
I highly recommend taking the time to go through Basic I/O, these are concepts you will re-use all the time.