0

I'm doing simple Client-Server applications which copying file from client to server and vice versa. I'm using Sockets of course. Apps shows Client menu with some options to choose: 1. Make Copy on sever 2. Get fileCopy from Server etc.

The issue is when I'm choosing first option, I can't do second one. I read about this exception, but i have no idea how to solve this problem. I'm looking forward for your ideas.

There is part of clientside code:

public Client(String host, int port) {
        try {
            s = new Socket(host, port);
            System.out.println("Witaj w programie");
            boolean finished = false;
            Scanner sc = new Scanner(System.in);
            while(!finished){
                System.out.println("\n\n1.Zrob kopie zapasowa pliku");
                System.out.println("2. Przywroc kopie");
                System.out.println("0.Zakoncz");
                char c = sc.nextLine().charAt(0);
                switch(c){
                case '1':
                    this.sendMessage(1);
                    makeCopy(s);
                    //s.close();
                    break; ...

sendMessage method code:

public void sendMessage(int message_id) throws IOException{
        oos = new ObjectOutputStream(s.getOutputStream());
        ois = new ObjectInputStream(s.getInputStream());
        oos.writeInt(message_id);
        oos.flush();
    }

and makeCopy method code:

private void makeCopy(Socket clientSock) throws IOException {
        File file = new File("D:\\klient\\doKopii.bmp");
        DataOutputStream dos = new DataOutputStream(clientSock.getOutputStream());
        FileInputStream fis = new FileInputStream(file);
        byte[] buffer = new byte[4096];

        while (fis.read(buffer) > 0) {
            dos.write(buffer);
        }

        fis.close();
        dos.close();
    }

Download copy from Server code:

private void saveFile(Socket clientSock) throws IOException {
        //DataInputStream dis = new DataInputStream(clientSock.getInputStream());
        FileOutputStream fos = new FileOutputStream("D:\\klient\\przywroconaKopia.bmp");
        File zSerwera = new File("D:\\serwer\\kopiaPliku.bmp");
        byte[] buffer = new byte[4096];

        int filesize = (int)zSerwera.length();
        int read = 0;
        int totalRead = 0;
        int remaining = filesize;
        while((read = ois.read(buffer, 0, Math.min(buffer.length, remaining))) > 0) {
            totalRead += read;
            remaining -= read;
            System.out.println("read " + totalRead + " bytes.");
            fos.write(buffer, 0, read);
        }

        //fos.close();
        //ois.close();
    }

I am aware of that this does not work because of DataOutputStream closing which means socket is also closed. I deleted this line, but after choosing one option then second (when first one has done), application just freezes.

Infexo
  • 3
  • 4

2 Answers2

0

There are several problems here.

  • You need to send the file length ahead of the file, and read exactly that many bytes at the receiver, as shown in this answer.
  • Don't mix stream types, and don't keep creating new streams. Use the same ObjectInputStream/ObjectOutputStream pair for the life of the socket, at both ends.
Community
  • 1
  • 1
user207421
  • 305,947
  • 44
  • 307
  • 483
  • I don't understand your advice completely. Now im using ObjectInputStream and ObjectOutputStream only. But where do i have to create those streams ? When i moved "oos" and "ois" streams creations outside sendMessage method, app gives more exceptions than before. – Infexo Apr 23 '16 at 19:10
  • You 'don't understand the advice completely' even though you've accepted an answer that says exactly the same thing? and which is only a partial answer? – user207421 Apr 25 '16 at 10:24
  • Consider that you've answered earlier and after your pust i didnt get your advice. After Priyamal's answer i understood what I was doing wrong. Sorry that I can't delete comments... Anyway thanks. – Infexo Apr 25 '16 at 12:01
0
    oos = new ObjectOutputStream(s.getOutputStream());
    ois = new ObjectInputStream(s.getInputStream());

public void sendMessage(int message_id) throws IOException{
        oos.writeInt(message_id);
}

make oos and ois as instance variables and make sure that they are instantiated only for one single time. why you have to get a dataoutput stream seperately you can send byte array in same objectoutputstream

private void makeCopy(Socket clientSock) throws IOException {
        File file = new File("D:\\klient\\doKopii.bmp");
        FileInputStream fis = new FileInputStream(file);
        byte[] buffer = new byte[4096];

        while (fis.read(buffer) > 0) {
            oos.write(buffer);
        }
}

this is not very good coding practise bt maybe u should try this approach

Priyamal
  • 2,919
  • 2
  • 25
  • 52
  • It helped me to some extent, but now i have problem with saveFile method. It creates new File but it doesnt write content/bytes to it (let's see edited post please) – Infexo Apr 23 '16 at 20:10
  • seriously you have to ask another question in the same post ?. what will you do if you get another error after this one , – Priyamal Apr 23 '16 at 20:11
  • here is an article on how to write to a file reading an byte array http://www.java2s.com/Code/Java/File-Input-Output/Readfiletobytearrayandsavebytearraytofile.htm . may be you should consider marking this as the correct answer . since you got the answer. the second question was asked after you got the answer for the first edit – Priyamal Apr 23 '16 at 20:23