Search code examples
javafilesocketstransfer

Java Send file via Socket


I'm writing a class for 2-way sending file via Sockets in Java Here on GitHub is it. Everything is good until file receiving finished. Shortly:

  • in client.java is hardcoded way to C:\Maven\README.txt
  • firstly I send filename
  • then I send file length
  • at third step I'm sending file from FileInputStream to DataOutputStream

On client:

byte[] bytes = new byte[(int)forSend.length()];
InputStream fin = new FileInputStream(forSend);
int count;
while ((count = fin.read(bytes)) > 0) {
    out.write(bytes, 0, count);
}
fin.close();
fout = new FileOutputStream(filename);
byte[] bytes = new byte[length];
System.out.println("receiving file...");
int count;
while ((count = in.read(bytes)) > 0) {
    fout.write(bytes, 0, count);
}
fout.flush();
fout.close();
  • file on server is completely received (the same length and content)

When I'm trying to add code for writing something to socket after that, after start server and client are waiting for something (I don't know what)

Previously I meet this situation when lost one DataInputStream reading (message sent from server but there was no reciever on client for this message). But currently I'm trying to add flag which is changed after file transfer finished and check for it's state later. It's work both on server and client, but adding read/write from/to Socket return me back to situation when both server and client are wait for something.

What's wrong now?


Solution

  • My friend Denr01 helped me, so my mistake was control of file length, I don't have it anywhere in my question. And because of that my "finishing" confirmation was writen to file. The way to solve problem is in sender:

    int read = 0;
    int block = 8192;
    int count = 0;
    byte[] bytes = new byte[block];
    while (read != forSend.length()) {
        count = fin.read(bytes, 0, block);
        out.writeInt(count);
        out.write(bytes, 0, count);
        read += count;
        System.out.println("already sent " + read + " bytes of " + forSend.length());
    }
    
    1. Sender read bytes and write in count number of them
    2. It send count to reciever, so reciever will know how many bytes to recieve in current loop iteration
    3. Then Sender send block of bytes and increments a counter of bytes read
    4. Repeating this while counter not equal to file length

    In sender:

    int block = 8192;
    int count = 0;
    int read = 0;
    byte[] bytes = new byte[block];
    System.out.println("recieving file...");
    while (read != length) {
        block=in.readInt();
        in.readFully(bytes, 0, block);
        fout.write(bytes, 0, block);
        read += block;
        System.out.println("already recieved " + read + " bytes of " + length);
    }
    
    1. Make byte array with length equal to sender's block length
    2. In every iteration firstly read next block length and then read this count of bytes
    3. Increment reciever's counter
    4. Repeat this while counter is not equal to file length which was recieved previously

    In this case we have control of each file reading iteration and always know how many bytes to recieve, so when all the bytes recieved files are identical and next "messages" will not be writen into file.