2012-05-22 4 views
3

이것은 특정 컴퓨터에있을 때만 발생하는 약간의 모호한 문제입니다. 오늘 학교의 XP 컴퓨터에서이 문제가 발생했으며 가정용 컴퓨터 (W7)에서이를 복제 할 수 없습니다. (: int avail, InputStream socket, byte[] buffer, String output) :InputStream의 사용 가능()이 멈추는 경향이 있습니다

    while((avail = input.available()) > 0) 
        { 
         read = input.read(buffer); 
         output += new String(buffer, 0, read); 
        } 

데이터를 사용할 수 없을 때까지 감 (모든 데이터를 읽을 수 있도록 보인다 어쨌든

는 읽기/자바 소켓에 쓰기는이 코드를 사용할 때마다 문제가 될 경향이있다 임시 버퍼로, 문자열로) 그러나 학교 컴퓨터 (IE7을 사용하여 테스트)에서 모든 것이 어떻게 든 일시 중지됩니다. 나는 스레드가 단지 끝점에 도달하지 않고 계속 실행되기 때문에 input.available()이 어떻게 든 블록을 일으키는 것으로 생각하고 있습니다 ... 효과적으로 어딘가에 일시 중지합니다.

오하이오, 내가 언급 한 것을 잊어 버렸습니다 : 언제든지 이것을 디버그 모드로 실행하고 각 라인을 단계별로 수행 할 때마다 완벽하게 작동해야합니다 ... 더 혼란 스럽습니다.

이 문제를 재현하기 위해 집에 왔을 때 Firefox와 IE8만으로도 제대로 작동합니다. 나는 이것에 대한 더 나은 대안이 무엇인지 모릅니다.

PS : 버퍼가 충분히 크고 난 그냥 사용 경우

    read = input.read(buffer); 
        output += new String(buffer, 0, read); 

그냥 잘 작동하지만 전송 된 데이터가 버퍼 크기를 초과 할 걱정은 항상있다.

+2

입력의 끝이 감지되거나 일부 데이터를 사용할 수있을 때까지 '읽기'가 차단됩니다. 실제로'available()> 0'은 어떤 데이터가 블로킹없이 사용 가능하다는 것을 나타 내기 때문에'available()'는 단지 _estimate_라는 것을 기억하는 것이 중요합니다. –

답변

3

당신은 available() 잘못된 길을 생각하고 있습니다. 해당 방법 tells you approximately how many bytes can be read right now, 차단하지 않고. 일반적으로 받아 들여지는 관용구는

int length; 
while ((length = in.read(buffer)) != -1) { 
    output += new String(buffer, 0, length); 
} 

또는 이와 유사한 내용 (컴파일/테스트되지 않음)입니다.

업데이트 : "스트림의 끝"이라는 개념을 잘못 이해했다고 생각합니다. "스트림의 끝"은 읽으려는 모든 데이터를 읽었 음을 의미하지 않습니다. 그것은 읽지 않을 것이고 앞으로도 없을 것이라는 것을 의미합니다. 예를 들어, 파일을 읽었을 때 파일을 읽었을 가능성이 있습니다. 즉, 인 메모리 바이트 배열에서 읽음을 의미 할 수도 있습니다. 그것들은 "스트림의 끝"입니다.

귀하의 질문에 귀하가 reading from a Socket임을 나타내거나 적어도 묵시적으로 말했습니다. 연관된 소켓이나 연결의 원격 종료가 닫힐 때까지는 스트림의 끝까지 도달하지 못할 것이라는 것을 알고 계십니까? 그것으로부터 약간의 데이터를 받았기 때문에 스트림의 끝이되지는 않습니다.

+0

방금 ​​시도해 보았고 읽으려고 멈추었을 것 같습니다. –

+1

[read()] (http://docs.oracle.com/javase/6/docs/api/java/io/InputStream.html#read%28byte [] % 29)에서 차단은 마지막에 도달 할 때까지 예상됩니다 스트림의. 하천의 끝에 도달했다는 증거가 있습니까? –

+0

글쎄, 내가 그것을 디버깅 할 때 전체 스팀 (출력에 올바른 데이터가 있음)을 읽은 다음 while 문으로 되돌아 간다. 그리고 계속 진행할 수 없다. –

1

왜 버퍼 된 리더를 사용하지 않습니까? 예 :

BufferedReader reader = new BufferedReader(new InputStreamReader(input)); 
    String output = ""; 
    try { 
     String readLine = null; 
     while ((readLine = reader.readLine()) != null) { 
      output += readLine + "\n"; 
     } 
    } catch (IOException e) { 
     System.err.println("Error: " + e); 
    } 
    System.out.println("Read from Socket:" + output); 
+0

업데이트했습니다. 나는 이것이 효과가 있어야한다는 것을 알고 있지만 같은 문제가 있습니다. –

+0

그리고 이것을 실행하면 디버그 할 때도 작동하지 않습니까? – Jeshurun

1

코드가 잘못되었습니다. 이는 available()의 오용입니다. 모든 작업은 차단없이 읽을 수있는 바이트 수를 알려줍니다. 피어에 의해 전송 될 바이트 수를 나타내는 데 사용할 수 없으며 피어 메시지와 필요한 관계가 없습니다. TCP에는 메시지가없고 바이트 스트림 만 있습니다. EOS로 읽으려면 available() 테스트를 제거하고 -1을 반환 할 때까지 읽으십시오. 메시지를 읽으려면 피어가 어떻게 든 메시지를 구분해야합니다. 아웃 오브 밴드 (out-of-band) 터미네이터, 길이 단어 접두어 또는 객체 직렬화 (XML) 또는 XML과 같은 자체 기술 프로토콜

중단 점을 사용하여 타이밍을 급격하게 변경하기 때문에 디버그 모드에서 작동합니다. 이것은 당신이하고있는 일이 정확하지 않다는 것을 보여주는 또 하나의 증거입니다.

관련 문제