1

I've created a program that will send a file to client. I've test on normal text file, it had sent to the client fully with no loss. But when I try to send some zip file, The output file is empty. What should I do?

Server.java

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

class Server {
    public static void main(String[] args) throws IOException {
        ServerSocket serverSocket = null;
        Scanner scan = new Scanner(System.in);
        String fileSend;
        System.out.print("Type the path to the file to send >> ");
        fileSend = scan.nextLine();
        try {
            serverSocket = new ServerSocket(5467);
        } catch (Exception e) {
            System.out.println("Could not bind to port 5467, Maybe address is already is use or you need to run as administrator");
            scan.close();
            return;
        }
        System.out.println("Listening on port 5467");
        System.out.println("Waiting for the connection...");
        while (true) {
            File FileSend = null;
            Socket socket = serverSocket.accept();
            OutputStream out = socket.getOutputStream();
            System.out.println("Accepted connection : " + socket);
            //รับข้อมูลจาก Client เข้ามา
            InputStream in = socket.getInputStream();
            DataInputStream dataIn = new DataInputStream(in);
            String login = dataIn.readUTF();
            String password = dataIn.readUTF();
            String result = "You credential is ";
            if (login.equals("1c18b5cdef8f9b4c5d6b2ad087265e597d1d4639337b73a04a335103c00ec64b") && password.equals("1c18b5cdef8f9b4c5d6b2ad087265e597d1d4639337b73a04a335103c00ec64b13d0b73358bfa8978dfaaf180565bcfecd3dc0631cda525920865145fb3fa131")) {
                result += "correct";
            } else {
                result += "incorrect";
            }
            DataOutputStream dataOut = new DataOutputStream(out);
            dataOut.writeUTF(result);
            FileSend = new File(fileSend);
            ObjectOutputStream out1 = new ObjectOutputStream(socket.getOutputStream());
            System.out.println("Sending file...");
            out1.writeObject(FileSend);
            //ส่งข้อมูลกลับไปยัง Client
        }
    }
}

Client.java

import java.io.*;
import java.net.*;
import java.nio.charset.StandardCharsets;
import java.util.Scanner;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Client {
    public static void main(String[] args) throws IOException, NoSuchAlgorithmException, ClassNotFoundException {
        Socket socket = null;
        String PlainLogin;
        String FileOut;
        String PlainPassword;
        Scanner scan = new Scanner(System.in);
        System.out.print("What is the IP address of the server >> ");
        String host = scan.nextLine();
        try {
            socket = new Socket(host, 5467);  //หรือกำหนดเป็น  127.0.0.1
        } catch (ConnectException | NullPointerException e) {
            System.out.println("Connection Refused, Have you run the server first?");
            scan.close();
            return;
        }

        OutputStream out = socket.getOutputStream();
        DataOutputStream dataOut = new DataOutputStream(out);
        System.out.println("Connection Established");
        System.out.println("Credential Required, Please login");
        System.out.print("Type your username >> ");
        PlainLogin = scan.next();
        System.out.print("Type your password >> ");
        PlainPassword = scan.next();
        MessageDigest md = MessageDigest.getInstance("SHA-256");
        byte[] hashInBytes = md.digest(PlainLogin.getBytes(StandardCharsets.UTF_8));

        StringBuilder sb = new StringBuilder();
        for (byte b : hashInBytes) {
            sb.append(String.format("%02x", b));
        }
        String HashedLogin = sb.toString();

        byte[] hashInBytesP = md.digest(PlainPassword.getBytes(StandardCharsets.UTF_8));

        for (byte b : hashInBytesP) {
            sb.append(String.format("%02x", b));
        }
        String HashedPassword = sb.toString();
        dataOut.writeUTF(HashedLogin); //ลำดับในการส่งข้อมูล ต้องตรงกับลำดับในการรับข้อมูลทางฝั่ง Server
        dataOut.writeUTF(HashedPassword);
        InputStream in = socket.getInputStream();
        DataInputStream dataIn = new DataInputStream(in);
        String str = dataIn.readUTF();
        if (str == "Your credential is incorrect") {
            System.out.println(str);
            socket.close();
            scan.close();
            return;
        } else {
            System.out.println(str);
            // Writing the file to disk
            // Instantiating a new output stream object
            System.out.print("Type any file name you want >> ");
            scan.nextLine();
            FileOut = scan.nextLine();
            File SaveFile = new File(FileOut);
            ObjectInputStream in1 = new ObjectInputStream(socket.getInputStream());
            File receivedFile = null;
            receivedFile = (File) in1.readObject();
            Scanner sc = new Scanner(receivedFile);
            PrintWriter printer = new PrintWriter(SaveFile);
            while(sc.hasNextLine()) {
              String s = sc.nextLine();
              printer.write(s);
            }
            socket.close();
            dataIn.close();
            printer.close();
            sc.close();
            scan.close();
            System.out.println("Done");
        }
    }
}

I expect the zip file to be send and not corrupt, But the file is empty on output.

  • 1
    why are you using a `ObjectOutputStream` to send a file? – Scary Wombat Aug 14 '19 at 06:01
  • A scanner is made for text files, and doesn't handle binary files well. Also, you are sending only the path to the file over the socket, and not the actual file contents themselves. – Ferrybig Aug 14 '19 at 06:03

1 Answers1

2

You are using object streams sending a File object. That's not what you think it is. A File is an object that represents a file system pathname. It doesn't represent the file's contents.

So what your code actually does is:

  • Sends hashed username and password.
  • Check them on the server side
  • Send a File.
  • On the server side, "open" the File and copy its contents.

But you are opening the File in the context of the server's file system, not the client's file system, so no data is being copied from the client to the server.

You are also using Scanner to copy the (wrong) file. Generally speaking, that won't work correctly for non-text files. The safest way to copy data irrespective of its "type" is to use binary streams.

If you want to send file contents, don't use ObjectInputStream and ObjectOutputStream to send the pathname. Instead, use plain OutputStream::write(...) and OutputStream::read(...) and a loop to copy the file data:

  • The client side should read bytes from the (client-side) local file and copy to the socket stream.

  • The server side should read bytes from the socket and write to a (server-side) local file.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216