Поведение синхронизации Java Socket - PullRequest
1 голос
/ 07 октября 2011

Я пытался решить проблему многими способами, но безуспешно, и я также искал информацию на этом форуме, но с теми же результатами, поэтому мы идем.

Я на самом деле делаю серверный демон, который принимаетклиент запрашивает, а затем (сервер) передает все файлы, содержащиеся в определенной папке.Я собираюсь опубликовать код sendFileData (на сервере) и receiveFileData (на клиенте).

Сервер использует:

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();
}

А на стороне клиента:

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());

    }

В коде receiveFileData, если я не помещаю Thread.sleep (1) или System.out.println () или что-либо еще, кому требуется время для выполнения, я не получаю данные вправильный путь на клиенте, потому что readInt () возвращает очень большое число, случайно отрицательное или положительное (что подразумевает кучу нехватки памяти и другие исключения).

Конечно, это что-то о синхронизации, но я думаю, что схема передачи междуоба метода верны (возможно, клиент слишком медленный, а сервер слишком быстрый).

Что происходит ??Потому что я не хочу ставить Thread.sleep, я думаю, это не очень хорошее программирование.

Большое вам спасибо!

1 Ответ

1 голос
/ 08 октября 2011

is.read (в байтах) не гарантирует заполнение предоставленного байтового массива.Вам нужно проверить его возвращаемое значение, чтобы увидеть, сколько байтов было прочитано или (лучше) использовать readFully ().

Sleep (), вероятно, просто позволяет время, чтобы все байты были возвращены из сокета.

...