-1

I'm having trouble running these two threads in Java. I have two methods in the client class and in each method they both have a socket of different ports but when I run the client, i see the error for a split second of one of the threads but the other one that sends the file over works.

Any help?

ClientApp.java

public static void main(String[] args) throws UnknownHostException, IOException, InterruptedException {
    Thread getFileThread = new Thread() {
        public void run() {
            Client client = new Client();

            try {
                client.getTheFile("girlwithmask.jpg");
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };


    Thread getListOfFilesThread = new Thread() {
        public void run() {
            Client client = new Client();

            ArrayList<String> listOfFiles = null;
            try {
                listOfFiles = client.getFileList();
                System.out.println(listOfFiles.get(1));
                notify();
            } catch (ClassNotFoundException | IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
    };

    getListOfFilesThread.start();
    getFileThread.start();
}

Client.java

    public class Client {
        private static final int PORT = 2665;
        private static String HOST = "localhost";

        Client() {

        }

        public void getTheFile(String filename) throws UnknownHostException, IOException {
            filename = "girlwithmask.jpg";  ///this is temporary

            int filesize = 5000000;   //buffer size 5mb
            int bytesRead;
            int currentTotalNumberOfBytes = 0;

            //connect to port on server - server waits for this after running socket.accept() in the Server class
            Socket socket = new Socket(HOST, PORT);

            byte[] byteArray = new byte[filesize];   //create a byte array of 5mb
            InputStream inputStream = socket.getInputStream();  //channel to to server
            FileOutputStream fileOutStream = new FileOutputStream("myClientFiles/" + filename);
            BufferedOutputStream bufferOutStream = new BufferedOutputStream(fileOutStream);

            bytesRead = inputStream.read(byteArray, 0, byteArray.length);
            currentTotalNumberOfBytes = bytesRead;

            do { //read till the end and store total in bytesRead and add it to currentTotalNumberOfBytes
                bytesRead = inputStream.read(byteArray, currentTotalNumberOfBytes, (byteArray.length - currentTotalNumberOfBytes));
                if (bytesRead >= 0) {
                    currentTotalNumberOfBytes += bytesRead;
                }
            } while (bytesRead > -1); // when bytesRead == -1, there's no more data left and we exit the loop

            bufferOutStream.write(byteArray, 0, currentTotalNumberOfBytes); //write the bytes to the file

            bufferOutStream.flush();
            bufferOutStream.close();
            socket.close();

        }

        public ArrayList<String> getFileList() throws UnknownHostException, IOException, ClassNotFoundException {
            Socket socket = new Socket("localhost", 9999);
            ArrayList<String> titleList = new ArrayList<String>();

            ObjectInputStream objectInput = new ObjectInputStream(socket.getInputStream());

            Object object = objectInput.readObject();
            titleList = (ArrayList<String>) object;
            // System.out.println(titleList.get(2));

            return titleList;
        }
    }

I'm not sure what is going on here. Been working with this for a couple of hours.

Dean J
  • 39,360
  • 16
  • 67
  • 93
franklinexpress
  • 1,149
  • 14
  • 44

1 Answers1

2

In the absence of an actual error, or indeed question, all we can do is critique your code:

 byte[] byteArray = new byte[filesize];   //create a byte array of 5mb

You don't know what filesize is. You've hardcoded a guess of 5000000. This will not work for any case where the filesize is bigger than 5000000 which might be very often. There is an approach where you don't need to know the filesize: nor do you need a buffer the size of the whole file in the first place. You're assuming the file fits into memory and that the file length fits into an int. Both assumptions may be wrong. Use a smaller buffer size of 8192 or some such reasonable number which is usually a multiple of 1024 to get a good memory alignment. Hard-coding a big size of 5000000 has the drawbacks mentioned.

InputStream inputStream = socket.getInputStream();  //channel to to server
FileOutputStream fileOutStream = new FileOutputStream("myClientFiles/" + filename);
BufferedOutputStream bufferOutStream = new BufferedOutputStream(fileOutStream);

You don't really need the BufferedOutputStream with this code, or at least with this code as it's going to be, but let it pass for now.

bytesRead = inputStream.read(byteArray, 0, byteArray.length);
currentTotalNumberOfBytes = bytesRead;
do { //read till the end and store total in bytesRead and add it to currentTotalNumberOfBytes
    bytesRead = inputStream.read(byteArray, currentTotalNumberOfBytes, (byteArray.length - currentTotalNumberOfBytes));
    if (bytesRead >= 0) {
        currentTotalNumberOfBytes += bytesRead;
    }
} while (bytesRead > -1); // when bytesRead == -1, there's no more data left and we exit the loop
bufferOutStream.write(byteArray, 0, currentTotalNumberOfBytes); //write the bytes to the file

To make this code shorter you might want to change it to the canonical form:

int count;
byte[] buffer = new byte[8192];
while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

substituting variable names as appropriate. You will:

  1. Save memory
  2. Reduce latency
  3. Have clear well-tested code that's been working for 18 years.

    bufferOutStream.flush();
    

flush() before close() is redundant.

    bufferOutStream.close();
    socket.close();

Closing the socket after closing its output stream (or input stream) is redundant. Just close the output stream. In a finally block.

Wolfgang Fahl
  • 15,016
  • 11
  • 93
  • 186
user207421
  • 305,947
  • 44
  • 307
  • 483
  • what is the 8192 comment about? I didn't understand it – Wolfgang Fahl Jun 30 '15 at 03:52
  • @WolfgangFahl; reading a buffer of five million bytes is, uh, unusual. Reading a buffer of somewhere between 1k and 8k bytes at a time is normal/expected. 8k is 8192, 2 ^ 13, and is a pretty typical buffer size to use here. – Dean J Jun 30 '15 at 04:17
  • @WolfgangFahl or see this SO article on filesystem block sizes, which is what you're normally trying to match up with there. http://stackoverflow.com/questions/236861/how-do-you-determine-the-ideal-buffer-size-when-using-fileinputstream – Dean J Jun 30 '15 at 04:17