2013-06-23 4 views
2

Im은 TCP를 통해 내 서버에 연결하는 간단한 소켓 앱을 만듭니다. 때때로 2 바이트 값을 읽을 필요가 있습니다. 따라서 다음과 같이됩니다.Java 소켓 - 손실 된 바이트 및 100 % 프로세서 전력 소비량

public byte[] read(int bytes) 
{ 
    byte b[] = new byte[bytes]; 
    try { 
     in.read(b); //in is InputStream from properly connected Socket.getInputStream() 
    return b; 
    } catch (IOException e) { 
     return null; 
    } 
} 

이 함수는 주어진 바이트 수를 받아서 배열로 반환해야합니다. 문제는 가끔 휴식을 취하기 전에 1 바이트를 읽고 이상한 데이터를 반환한다는 것입니다. (실제로, 하나 개의 코어)

public byte[] read(int bytes) 
{ 
    byte b[] = new byte[bytes]; 
    try { 
     while (in.available()<bytes); //It does the thing 
     in.read(b); 
    return b; 
    } catch (IOException e) { 
     return null; 
    } 
} 

을하지만 루프는 프로세서 전력의 100 %를 사용하고 있습니다 인 :이 충분한 데이터를 읽을 경우

byte a[]=read(2); //Program is blocked here untill some bytes arrive... 
System.out.prntln(a[0]); //always correct 
System.out.prntln(a[1]); //unprintable character (probably 0 or -1) 

내 빠른 수정은 루프를 확인하면서 추가했다 매우 짜증나. 해당 함수를 다시 쓰는 방법이 있습니까 (param과 반환 값이 정확히 같아야합니다). 그러면 올바르게 작동합니까?

고맙습니다 :

+1

여기 왜이 작업을 수행해야합니까? 나는 마침내 {}와 내 문제 사이에 어떤 현실도 찾을 수 없다. 내가 틀린가? –

+0

예를 들어 열 때 리소스를 닫아야한다는 의견이 있습니다. InputStreams – nachokk

+0

더 이상 InputStream을 필요로하지 않을 때 닫습니다. 이는 단지 도우미 기능 일뿐입니다. 또한 소켓이있을 때 스트림이 자동으로 닫히지 않습니까? –

답변

7

예. 귀하의 빠른 수정은 나쁜 생각입니다. 실제로 available을 사용하는 코드는 손상되었을 수 있습니다. 여기

내가이 할 거라고 방법은 다음과 같습니다에 "투표"스트림이 available()를 사용하여 필요가 없습니다

public byte[] read(int bytes) throws IOException { 
    byte b[] = new byte[bytes]; 
    int pos = 0; 
    while (pos < b.length) { 
     int nosRead = in.read(b, pos, b.length - pos); 
     if (nosRead == -1) { 
      return null; // Not the best idea ... see below. 
     } else { 
      pos += nosRead; 
     } 
    } 
    return b; 
} 

. 잠잘 필요가 없습니다. read은 적어도 하나의 바이트를 읽었거나 "스트림 끝"에 적합 할 경우에만 반환한다는 사실을 이용합니다. 나는 또한 그것을 생각하지 않는다


참고는 당신의 read 방법이 실패 null 경우 반환 할 권리입니다. 예외를 던지거나 ... in.read() 호출에서 IOException을 전달하는 것이 좋습니다.

이것은 내 재 작성에도 적용됩니다 ... 그 점에서 코드의 동작을 변경하고 싶지 않았습니다.

+0

정확하게 필요한 것. 다른 대답은 좋았어. 내가 그걸 받아들이면 너 괜찮 니? (C 씨가 너보다 처신이 덜하기 때문에). 도움을 주셔서 감사합니다 :) –

+1

@kittyPL - 불행히도, "Mr C"답변을 자세히 읽는다면, 여러 가지 실수가 있습니다. (코드에서 실수가 무엇인지 알아 내기 위해 당신에게 맡길 것입니다. 그러나 NIO에 대한 그의 충고는 잘못되었거나 최소한 단순화되었습니다.) –

+0

지금 봅니다. 희망이 그는 이것을 바꿀 것입니다 :) –

2

멀리 던져서 DataInputStream.readFully()를 사용하십시오.