简体   繁体   English

Java Socket同步行为

[英]Java Socket synchronization behavior

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). 我将发布sendFileData(在服务器上)和receiveFileData(在客户端上)的代码。

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];
        auxiliar[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). 在receiveFileData代码中,如果我不放置Thread.sleep(1)或System.out.println()或需要花费时间执行的任何操作,则我没有以正确的方式在客户端上接收数据,因为readInt ()返回一个很大的随机负数或正数(这意味着堆内存不足和其他异常)。

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. 因为我不想放一个Thread.sleep,所以我认为这里的编程不好。

Thank you so much! 非常感谢!

is.read(bytes) is not guaranteed to fill the supplied byte array. is.read(bytes)不能保证填充提供的字节数组。 You need to check its return value to see how many bytes were read or (better) use readFully(). 您需要检查其返回值以查看已读取多少字节,或者(更好)使用readFully()。

The sleep() probably just allows time for all bytes to have been returned from the socket. sleep()可能只允许所有时间从套接字返回所有字节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM