Search code examples
javamultithreadingsocketsclient-serverdata-transfer

Java socket is stuck on readUTF()


I'm trying to transfer files over a socket in Java, my current approach for the server is:

  1. Create new Thread
  2. Thread sends file name using dos.writeUTF()
  3. Thread sends file size using dos.writeLong()
  4. Thread sends file using dos.write()

Where each Thread represents a client and dos is an instance of DataOutputStream.

Now, on the client I'm doing the same thing but reading instead of writing:

  1. Read file name using dis.readUTF()
  2. Read file size using dis.readLong()
  3. Read file using dis.read()

Where dis is an instance of DataInputStream.
The problem is: when sending one file, everything goes right, but when I try to send 3 files, one after another, it looks like the server is writing everything correctly to the stream as expected but the client (After the first file, which means this starts happening from the second file) is stuck on dis.readUTF() and can't move on.

I've tried fixing this for days but can't get anything to work.
Here's the source code:

SERVER:

Main.java

 public class Main {
    public static void main(String[] args) {
        boolean boolDebug = true;//TODO REMOVE THIS!!
        ServerSocket serverSock = null;
        List<Socket> clientSocks;
        List<ClientThread> clientThreads;
        try {
            serverSock = new ServerSocket(9090);
        } catch(Exception e){
            e.printStackTrace();
        }
        clientSocks = new ArrayList<>();
        clientThreads = new ArrayList<>();
        ServerSocket finalServerSock = serverSock;

        System.out.println();
        System.out.println("Listening for incoming connections\n");
        new Thread(){
            @Override
            public void run() {
                super.run();
                while (true) {
                    try {
                        Socket newSock = finalServerSock.accept();
                        clientSocks.add(newSock); //FIXME Remove sockets when closed
                        Thread thread = new ClientThread(newSock, usr, psw);
                        thread.start();
                        clientThreads.add((ClientThread)thread);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }.start();
    }
}

ClientThread.java

public class ClientThread extends Thread {
    private Socket socket;
    private DataInputStream inStream;
    private DataOutputStream outStream;
    private String dbUser;
    private String dbPassword;

    public ClientThread(Socket socket, String DbUser, String DbPass) {
        this.socket = socket;
        this.dbUser = DbUser;
        this.dbPassword = DbPass;
    }

    @Override
    public void run() {
        try {
            inStream = new DataInputStream(socket.getInputStream());
            outStream = new DataOutputStream(socket.getOutputStream());
            sendFile("a.txt");
            sendFile("b.txt");
            sendFile("c.txt");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    void sendFile(String file){
        try {
            File f = new File(file);
            outStream.writeUTF(file);
            outStream.writeLong(f.length());
            FileInputStream fis = new FileInputStream(f);
            byte[] buffer = new byte[4096];

            while (fis.read(buffer) > 0) {
                outStream.write(buffer);
            }
            fis.close();
        }catch(Exception e){
            e.printStackTrace();
        }

    }
    int getSize(byte[] buffer,long remaining){
        try {
            return Math.toIntExact(Math.min(((long) buffer.length), remaining));
        }catch(ArithmeticException e){
            return 4096;
        }
    }

}

CLIENT: Main.java

class Main {

    static int getSize(byte[] buffer, long remaining) {
        try {
            return Math.toIntExact(Math.min(((long) buffer.length), remaining));
        } catch (ArithmeticException e) {
            return 4096;
        }
    }

    static void saveFile(Socket clientSock,DataInputStream dis) throws IOException {

        String fileName = dis.readUTF();
        File f = new File(fileName);
        FileOutputStream fos = new FileOutputStream(f);
        byte[] buffer = new byte[4096];

        long filesize = dis.readLong();
        int read = 0;
        int totalRead = 0;
        long remaining = filesize;

        while ((read = dis.read(buffer, 0, getSize(buffer, remaining))) > 0) {
            totalRead += read;
            remaining -= read;
            System.out.println("read " + totalRead + " bytes.");
            fos.write(buffer, 0, read);
        }
        fos.close();
    }

    public static void main(String[] args) throws Exception {
        Socket sock = new Socket("192.168.2.17", 9090);
        DataInputStream dis = new DataInputStream(sock.getInputStream());
        saveFile(sock,dis);
        saveFile(sock,dis);
        saveFile(sock,dis);

    }
}

Many thanks in advance, looking forward to fix this :(


Solution

  • Fixed by changing

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

    to

    int count;
    while ((count = fis.read(buffer)) > 0) {
        outStream.write(buffer, 0, count);
    }
    

    Inside ClientThread.java on the server side