2011-12-15 3 views
1

를 반환 판독 코드를 읽어자바 NIO SocketChannel에 항상 클라이언트 측에서 동일한 데이터

byte[] bytes = new byte[50]; //TODO should reuse buffer, for test only 
ByteBuffer dst = ByteBuffer.wrap(bytes); 
int ret = 0; 
int readBytes = 0; 
boolean fail = false; 
try { 
    while ((ret = socketChannel.read(dst)) > 0) { 
    readBytes += ret; 
    System.out.println("read " + ret + " bytes from socket " + dst); 
    if (!dst.hasRemaining()) { 
     break; 
    } 
    } 
    int pos = dst.position(); 
    byte[] data = new byte[pos]; 
    dst.flip(); 
    dst.get(data); 
    System.out.println("read data: " + StringUtil.toHexString(data)); 
} catch (Exception e) { 
    fail = true; 
    handler.onException(e); 
} 

문제는 socketChannel.read()와 항상 I가 리턴 버퍼를 체크 긍정적 반환 데이터가 중복 N 배이며 그것은 저수준 소켓 버퍼의 위치가 앞으로 움직이지 않는 것을 좋아한다. 어떤 생각?

답변

-2

1 : 버그가 아닐 수도 있습니다.

는 지속적를 잡하는 경우 -1 스트림의 끝에 ... http://docs.oracle.com/javase/1.4.2/docs/api/java/nio/channels/SocketChannel.html#read%28java.nio.ByteBuffer%29

를 참조

당신은 기대 ... [버퍼에서 읽을 데이터가 있다고 가정] read() 호출의 양수 값이면 데이터가 계속 읽히는 이유를 알아야합니다.

물론 신비는 원본 데이터 (즉, 데이터를 읽는 SocketChannel)에 있습니다.

2 : 가능한 문제

당신의 소켓 채널은 유한 진짜 파일에서 오는 경우에 대한 설명은 다음 파일이 정말 큰이며, 결국 읽기() 작업이 0을 반환합니다. .. 결국 ...

반면에 소켓 채널이 유한 한 것으로 예상되는 데이터 소스 (예 : 직렬화 된 객체 스트림)를 수신하는 경우 소스 코드 --- 아마도 당신의 유한 스트림은 점점 더 많은 데이터를 생산하고 있습니다 ... 그리고 당신은 그것을 정확하게 소비하고 있습니다.

3 : 마지막으로 몇 가지 조언

당신의 읽기 방법에의 ByteBuffer 입력을 재생 이러한 유형의 오류 디버깅을위한 트릭

: java.nio의의 ByteBuffer의 좋은 점은 그들이 때문에 것을 더 객체 오래된 byte [] 라이터를 지향한다면, 매우 세밀한 디버깅 작업을 수행 할 수 있습니다.

+0

빠른 재생 주셔서 감사합니다. 이 소켓 채널은 Netty 서버에 연결합니다. 서버에 한 요청을 보내면 서버는 48 바이트 만 반환하고 selector.select()가 반환되고 selectionKey는 읽을 수있는 경우에만 코드가 실행됩니다. 그래서 나는 완전히 혼란 스러웠다. –

+0

BTW, 제목에서 언급했듯이, socketChannel에서 읽은 것은 48 바이트의 서버 반환입니다. 문제는 항상 socketChannel에서 동일한 데이터를 읽을 수 있다는 것입니다. 그리고 데이터가 정확하므로 디코드 할 수 있으므로 결코 멈추지 않습니다 :-( –

+0

--- 코드에 버그가 없습니다. 어떤 데이터를 Netty에서 읽었는지 명확히 할 수 있습니까? – jayunit100

0

서버가 48 바이트 만 반환하는 경우 코드는 read() 메서드에서 차단되어 49 번째 및 50 번째 바이트를 가져와야합니다. 따라서 여러분의 '50'중 하나가 잘못되었거나 버퍼를 먼저 채우기보다는 코드를 읽고 처리하도록 코드를 다시 구성해야합니다. 그리고 이것은 항상 동일한 데이터를 가지고 있다고 생각하는 코드 일 수 없습니다. 그것에 대한 설명은 당신이해야 할 다음 읽기를 위해 같은 버퍼를 재사용한다면, get 후에 버퍼를 압축하지 못하게 될 것입니다.하지만 게시 된 코드는 그렇지 않습니다.