0

我正在尝试读取 SocketChannel 上的流而不定义字节数。

我想到的替代解决方案是将预定义大小的不同 ByteBuffer 存储到一个列表中,这将允许我之后分配一个接收大小的新 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();
}

关于如何解决这个问题的任何想法?

4

3 回答 3

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大小时考虑到这一点。

于 2014-03-12T23:52:16.633 回答
0

HTTP 响应流中的字节数不是“未定义的”。请参阅RFC。它由以下任一定义:

  1. EOS 在连接关闭的情况下(HTTP 1.0 或连接:关闭),
  2. Content-Length 标头,或
  3. 解码分块编码格式的结果。

必须以其中一种方式定义它,也许还有其他方式,这样 HTTP 持久连接才能工作,在此之后可能会有另一个响应。

我想知道你为什么要实现这个,当HttpURLConnection类已经存在时,以及已经正确实现所有这些的各种第三方 HTTP 客户端,以及除此之外的许多其他东西。

于 2014-03-12T23:53:10.157 回答
-1

解决方案是要摆脱循环,我必须调用:

sc.shutdownOutput();

关闭写入流而不关闭读取流并将 sc.read(buff) 设置为 -1

于 2014-03-13T21:00:32.747 回答