2011-10-07 4 views
1

여러 가지 방법으로 문제를 해결하려고했지만 성공하지 못했습니다.이 포럼에서도 정보를 찾았지만 같은 결과를 얻었으니 여기에 나와 있습니다.Java 소켓 동기화 동작

실제로 클라이언트 요청을 받아들이고 서버 (서버)가 특정 폴더에 포함 된 모든 파일을 전송하는 서버 데몬을 수행하고 있습니다. sendFileData (서버에서)와 receiveFileData (클라이언트에서)의 코드를 게시 할 것이다.

서버가 사용하는 다음 receiveFileData 코드에서

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

    } 

, 내가 Thread.sleep를 (1) 또는 System.out을 넣어하지 않는 경우 :

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

을 그리고 클라이언트 측에서 .println() 또는 누가 실행하는 데 시간이 걸리는지간에 readInt()는 무작위로 음수 또는 음수를 반환하기 때문에 클라이언트에서 올바른 방식으로 데이터를받지 못합니다 (메모리 및 기타 예외가 발생하여 힙을 의미 함) .

확실한 것은 동기화에 관한 것이지만 두 가지 방법 간의 스키마 이전은 정확합니다 (클라이언트가 너무 느리고 서버가 너무 빠름).

무슨 일입니까 ?? Thread.sleep을 넣고 싶지 않기 때문에 여기는 좋은 프로그래밍이 아닙니다.

정말 고마워요!

+0

얼마나 많은 다른 스레드가 receiveFileData()를 호출 할 수 있습니까? sendFileData()에 대해서도 같은 질문입니다 ... File -> File transfer를하고 있다면 ... byte [] 이외의 다른 것을 혼란시키는 이유는 무엇입니까? 데이터로드 앞에 하나의 int가 있어야 다른 쪽에서 예상 할 바이트 수를 알 수 있지만 그 외에는 원시 바이트 만 보내면됩니다. – claymore1977

+0

서버에는 새 연결 (accept())을 수신하는 스레드가 하나만 있습니다. 클라이언트가 서버에 연결을 시도하면 서버는 클라이언트와 서버 간의 데이터 흐름을 별도로 관리하는 새 스레드를 생성 한 다음 계속해서 청취합니다. 클라이언트 측에는 하나의 스레드 만 있습니다. 파일의 모든 바이트가 포함 된 전체 버퍼를 보내려고했으나 추락했다고 생각합니다 (지금 집에 없기 때문에 확인해야합니다). 답장을 보내 주셔서 감사합니다. – cabreracanal

+0

그리고이 코드는 변경되지 않은 전체 파일을 한 위치에서 다른 위치로 전송합니다. – claymore1977

답변

1

is.read (bytes)는 제공된 바이트 배열을 채우는 것이 보장되지 않습니다. 얼마나 많은 바이트가 읽혔는지 또는 더 잘 readFully()를 사용하는지 확인하려면 반환 값을 확인해야합니다.

sleep()은 아마 모든 바이트가 소켓에서 반환 된 시간을 허용합니다.

+0

오, 정말 고마워요, 제가 월요일에 시험해 볼게요. 괜찮 으면 대답을 받아 들일 것입니다. – cabreracanal

+0

정말 고마워요 !! readFully는 해결책 이었지만, 나는 또한 송신자에서 뭔가 잘못되었다 : 파일 길이 % 8187 == 0, 마지막 패킷에 대해 hasNext = 1이고 0이어야한다. 이제는 모두 잘된다! – cabreracanal