开发者

Java Socket synchronization behavior

开发者 https://www.devze.com 2023-04-11 17:23 出处:网络
I tried to solve the problem in many ways but without success and I have also looked for information in this forum but with same results, so here we go.

I tried to solve the problem in many ways but without success and I have also looked for information in this forum but with same results, so here we go.

I am actually doing a server daemon that accepts client requests and then it (the server) transfers all the files contained in a specific folder. I'm going to post the code of the sendFileData (on the server) and the receiveFileData (on the client).

The server uses:

public static void sendFileData(File file, Socket socket) throws FileNotFoundException, IOException, SocketException {
    byte[] auxiliar = new byte[8192];
    byte[] mybytearray = new byte[(int) file.length()];
    int longitud = mybytearray.length;

    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
    bis.read(mybytearray, 0, longitud);
    DataOutputStream os = new DataOutputStream(socket.getOutputStream());
    int paquetes = longitud / 8187;
    int resto = longitud % 8187;
    int i = 0;
    while(i<paquetes){//The length goes on the first 4 bytes and the 5th tells if there are more packets to send (8192 bytes or less).
        byte[] bytes = ByteBuffer.allocate(4).putInt(8187).array();
        auxiliar[0] = bytes[0];
        auxiliar[1] = bytes[1];
        auxiliar[2] = bytes[2];
        auxiliar[3] = bytes[3];
        auxiliar[4] = 1;
        for(int j = 5; j < 8192; j++){
            auxiliar[j] = mybytearray[i*8187+(j-5)];
        }
        os.write(auxiliar, 0, 8192);

        i+=1;
    }
    if(resto > 0){
        byte[] bytes = ByteBuffer.allocate(4).putInt(resto).array();
        auxiliar[0] = bytes[0];
        auxiliar[1] = bytes[1];
        auxiliar[2] = bytes[2];
        auxi开发者_Python百科liar[3] = bytes[3];
        auxiliar[4] = 0;
        for(int j = 5; j < resto+5; j++){
            auxiliar[j] = mybytearray[i*8187+(j-5)];
        }
        os.write(auxiliar, 0, resto+5);
    }
    os.flush();
}

And in the client side:

public static void receiveFileData(String nombreFichero, Socket s) throws IOException{
        File monitored = new File(nombreFichero);
        if(monitored.exists() == false){
            monitored.createNewFile();
        }
        byte[] mybytearray;
        DataInputStream is = new DataInputStream(s.getInputStream());
        FileOutputStream fos = new FileOutputStream(monitored);
        BufferedOutputStream bos = new BufferedOutputStream(fos);
        int bytesRead = 0;
        int hasNext = 1;
        do {
            bytesRead = is.readInt();//Leo longitud
            try {
                Thread.sleep(1);// HERE!!!!
            } catch (InterruptedException e) {
            }
//          System.out.println("Bytes read "+bytesRead );
            if(bytesRead <= 8187 && bytesRead > 0){
//              System.out.println("Bytes leídos "+bytesRead );
                hasNext = is.readByte();//Leo si hay más datos por enviar
                mybytearray = new byte[bytesRead];
                is.read(mybytearray);
                if(monitored.exists()){
                    synchronized(monitored){
                        bos.write(mybytearray, 0, mybytearray.length);
                    }
                }
                mybytearray = null;
            }else{
                System.out.println("Fuera de rango "+bytesRead);
            }
        }while(hasNext == 1);
        bos.close();
        mybytearray = null;
        System.out.println("Fichero recibido: "+monitored.getAbsolutePath());

    }

In the receiveFileData code, if I do not put a Thread.sleep(1) or a System.out.println() or whatever who takes time to execute, I am not receiving the data in the correct way on the client, because readInt() returns a very high number randomly negative or positive (which implies Heap out of memory and other exceptions).

Sure it's something about synchronization but I think the transfering schema between the two methods is correct (maybe the client is too slow and server too fast).

What is happening?? Because I do not want to put a Thread.sleep, this is not good programming here I think.

Thank you so much!


is.read(bytes) is not guaranteed to fill the supplied byte array. You need to check its return value to see how many bytes were read or (better) use readFully().

The sleep() probably just allows time for all bytes to have been returned from the socket.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号