1

在客户端,阅读代码:

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()总是返回正数,我检查了返回缓冲区,数据重复了N次,它喜欢低级套接字缓冲区的位置没有向前移动。任何想法?

4

2 回答 2

0

如果服务器只返回了 48 个字节,那么您的代码肯定在read()试图获取第 49 个和第 50 个字节的方法中被阻塞了。所以要么你的'50'是错误的,要么你将不得不重组你的代码来读取和处理你得到的任何东西,而不是先尝试填充缓冲区。这不可能是你认为你总是得到相同数据的代码。对此的解释是,如果您在下次读取时重用相同的缓冲区,则在获取后无法压缩缓冲区,您应该这样做,但您发布的代码没有这样做。

于 2011-12-15T21:53:40.350 回答
-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:解释你可能遇到的问题

如果您的套接字通道来自一个有限的真实文件,那么您的文件真的很大,最终,read() 操作将返回 0... 最终...

另一方面,如果您的套接字通道正在侦听您期望是有限的数据源(例如,序列化对象流),我会仔细检查源 --- 也许您的有限流只是在产生越来越多的数据......并且您正在正确地使用它。

3:最后一些建议

调试此类错误的一个技巧是使用 ByteBuffer 输入到您的 read 方法:java.nio 的 ByteBuffers 的好处是,由于它们比旧的 byte[] 编写器更面向对象,因此您可以做得很好-对其操作进行粒度调试。

于 2011-12-15T04:11:46.400 回答