2014-03-12 3 views
0

바이트 수를 정의하지 않고 SocketChannel에서 스트림을 읽으려고합니다.바이트 수가 정의되지 않은 SocketChannel에서 TCP를 통한 스트림 읽기

내가 생각한 대체 솔루션은 미리 정의 된 크기의 다른 ByteBuffers를 목록에 저장하여 나중에 수신 된 크기의 새 ByteBuffer를 할당하고 결과를 내부에 넣을 수있게하는 것입니다.

문제

차단 모드에 내가 있다는 것입니다 및 코드 확인 내가 읽기 방법에 따라 만들어진 루프를 떠나 유효한 상태를 찾을 수 없습니다 :

public static final Charset charsetUTF8 = Charset.forName("UTF-8"); 
public static final int BUFFER_SIZE = 1024; 

public static String getUnbounded(String st, SocketAddress address) throws IOException { 
    SocketChannel sc = SocketChannel.open(address); 
    sc.write(charsetUTF8.encode(st)); 
    List<ByteBuffer> listBuffers = new ArrayList<>(); 
    ByteBuffer buff = ByteBuffer.allocate(BUFFER_SIZE); 
    while(sc.read(buff) > -1){ 
     if(buff.remaining() == 0){ 
      listBuffers.add(buff); 
      buff.clear(); 
     } 
    } 

    listBuffers.add(buff); 
    ByteBuffer finalBuffer = ByteBuffer.allocate(BUFFER_SIZE * listBuffers.size()); 
    for(ByteBuffer tempBuff: listBuffers){ 
    finalBuffer.put(tempBuff); 
     tempBuff.clear(); 
    } 
    finalBuffer.flip(); 

    return charsetUTF8.decode(finalBuffer).toString(); 
} 

이 문제를 해결하는 방법에 대한 어떤 생각을?

+1

왜 ByteBuffer를 사용해야 할 필요가 있다고 생각하십니까? – kdgregory

+0

어떤 제안이 있습니까? Read 메서드를 더한 것만으로 ByteBuffer가 걸립니다. – Hosni

+1

왜 채널을 사용합니까? IO를 차단하고 데이터를 힙 할당 버퍼에 저장하려고합니다. 당신은 정말로 당신이 단순한'SocketInputStream'을 통해 * 아무것도 얻고 있다고 생각합니까? – kdgregory

답변

-1

해결책은 루프의 벗어나고 난 호출했다 :

판독 스트림을 닫지 않고 기입 스트림을 닫고 sc.read (광)

를 -1로 설정
sc.shutdownOutput(); 

+0

원래 물어 본 질문에 대한 해결책은 아닙니다. 그리고 당신은 보낸 사람에게'shutdownOutput()'*을 호출해야한다는 것을 분명히하지 않았다. * -1 – EJP

+0

나는 스트림을 닫을 필요가 있다는 것을 몰랐다. 나는 방금 떠날 수있는 방법이 필요했다. 루프 및 읽기() 메서드를 -1로 설정하고 질문에 그것을 말했다. – Hosni

+0

요점은 read() 메소드를 사용하지 않아야한다는 것입니다. HTTP 응답에 몇 바이트인지 알았어야합니다. – EJP

2

그냥 clear() 바이트 버퍼 일 수는 없습니다. 새 것을 할당해야합니다. 그렇지 않으면 동일한 버퍼가 listBuffers에 반복적으로 추가됩니다.

ByteBuffer buff = ByteBuffer.allocate(BUFFER_SIZE); 
while(sc.read(buff) > -1){ 
    if(buff.remaining() == 0){ 
     listBuffers.add(buff); 
     buff = ByteBuffer.allocate(BUFFER_SIZE); 
    } 
} 
if (buff.position() > 0) { 
    listBuffers.add(buff); 
} 

마지막 버퍼 (아마되지 않습니다) 가득, 당신은 계정에이 복용 finalBuffer 크기를 계산해야하지 않을 수도 있기 때문이다.

+0

clear() 메서드는 ByteBuffer를 저장 한 다음 지우고 read() 메서드를 사용하여 새 바이트를 내부에 넣습니다. – Hosni

+1

@Hosni - 예,하지만 매번 동일한 ** ByteBuffer 객체를'listBuffers'에 추가하고 있습니다. 결국, 루프가 종료 될 때 상태'buff'가 남아 있던지간에, 그것은 'buff'의 동일한 사본으로 가득 차게 될 것입니다. 'listBuffers'의 각 요소마다 별도의 객체가 필요합니다. –

+0

하지만 이미 선언하고 루프 외부에서 ByteBuffer를 만들었으므로 동일한 식별자가있는 다른 하나를 만들 수는 없습니다. – Hosni

0

HTTP 응답 스트림의 바이트 수가 '정의되지 않음'입니다. RFC을 참조하십시오. 그것은 하나에 의해 정의된다 :

  1. EOS를 폐쇄 연결의 경우 (HTTP 1.0 연결 닫기)
  2. 콘텐츠 길이 헤더 또는
  3. 청크를 복호화 한 결과를 인코딩 형식.

이러한 방법 중 하나에서 정의해야하며, HTTP 영구 연결이 작동 할 수 있도록 나머지가있을 수도 있습니다.이 경우 다른 응답이있을 수 있습니다.

HttpURLConnection 클래스가 이미 존재하는 이유와이 모든 것을 올바르게 구현 한 다양한 타사 HTTP 클라이언트 및 기타 많은 것들을 알고 싶습니다.

+1

http://tools.ietf.org/html/rfc2616#section-4.4 – kdgregory

+0

@kdgregory 감사합니다. 링크가 편집되었습니다. – EJP

+0

이것은 http 스트림과 함께 사용되는 예제이지만 모든 스트림에서 작동하지 않습니다. – Hosni