android - Android NIO - 无法从 SocketChannel 读取大数据,错误:BUFFER_UNDERFLOW
问题描述
我们正在尝试通过 NIO TCPs SocketChannel 读取大量数据。
代码适用于少量数据(小于 16 KB),但高于第一次,它将 16 KB 读入目标缓冲区,再次尝试读取剩余数据,但给出BUFFER_UNDERFLOW
异常。
基于文档
客户端正在从网络中读取部分数据,我们需要强制客户端再次读取。但是,
它没有发生在我们的代码中。我们正在使用以下代码:
protected ByteBuffer read(SocketChannel socketChannel, SSLEngine engine) throws Exception {
mPeerNetData.clear();
int waitToReadMillis = 50;
boolean exitReadLoop = false;
while (!exitReadLoop) {
int bytesRead = socketChannel.read(mPeerNetData);
if (bytesRead > 0) {
mPeerNetData.flip();
while (mPeerNetData.hasRemaining()) {
mPeerAppData.clear();
SSLEngineResult result = engine.unwrap(mPeerNetData, mPeerAppData);
switch (result.getStatus()) {
case OK:
mPeerAppData.flip();
exitReadLoop = true;
break;
case BUFFER_OVERFLOW:
mPeerAppData = enlargeApplicationBuffer(engine, mPeerAppData);
break;
case BUFFER_UNDERFLOW:
mPeerNetData = handleBufferUnderflow(engine, mPeerNetData);
break;
case CLOSED:
closeConnection(socketChannel, engine);
return null;
default:
throw new IllegalStateException("Invalid SSL status: " + result.getStatus());
}
}
} else if (bytesRead < 0) {
handleEndOfStream(socketChannel, engine);
return null;
}
Thread.sleep(waitToReadMillis);
}
return mPeerAppData;
}
上面的代码参考取自这里:
调试代码后,我们得到以下异常
javax.net.ssl.SSLException: Unable to parse TLS packet header
System.err: at org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:792)
com.amg.androidntg6poc W/System.err: at org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:733)
com.amg.androidntg6poc W/System.err: at org.conscrypt.ConscryptEngine.unwrap(ConscryptEngine.java:698)
2019-09-12 12:21:58.478 5040-6411/com.amg.androidntg6poc W/System.err: at thrift.transport.sslengine.TTLSClient.read(TTLSClient.java:194)
2019-09-12 12:21:58.485 5040-6449/com.amg.androidntg6poc I/System.out: 2019/09/12 12:21:58
2019-09-12 12:21:58.488 5040-6411/com.amg.androidntg6poc W/System.err: at thrift.transport.sslengine.TTLSClient.read(TTLSClient.java:168)
2019-09-12 12:21:58.488 5040-6411/com.amg.androidntg6poc W/System.err: at thrift.transport.TTcpTransport$2.canRead(TTcpTransport.java:721)
2019-09-12 12:21:58.489 5040-6411/com.amg.androidntg6poc W/System.err: at thrift.TReactor.threadProc(TReactor.java:215)
2019-09-12 12:21:58.489 5040-6451/com.amg.androidntg6poc I/System.out: 2019/09/12 12:21:58
2019-09-12 12:21:58.504 5040-6411/com.amg.androidntg6poc W/System.err: at thrift.TReactor.access$000(TReactor.java:30)
2019-09-12 12:21:58.504 5040-6411/com.amg.androidntg6poc W/System.err: at thrift.TReactor$1.run(TReactor.java:105)
2019-09-12 12:21:58.505 5040-6411/com.amg.androidntg6poc W/System.err: at java.lang.Thread.run(Thread.java:764)
2019-09-12 12:21:58.509 5040-6450/com.amg.androidntg6poc W/System.err: TException(E_TRANSPORT_CLOSED)
2019-09-12 12:21:58.510 5040-6450/com.amg.androidntg6poc W/System.err: at thrift.TServiceBroker.transportStatusChanged(TServiceBroker.java:548)
2019-09-12 12:21:58.510 5040-6450/com.amg.androidntg6poc W/System.err: at thrift.transport.TTransport$1.run(TTransport.java:258)
2019-09-12 12:21:58.511 5040-6450/com.amg.androidntg6poc W/System.err: at thrift.TReactor.threadProc(TReactor.java:148)
2019-09-12 12:21:58.511 5040-6411/com.amg.androidntg6poc D/ThriftGeneralService: connectionStatusChanged() :: 6
2019-09-12 12:21:58.511 5040-6411/com.amg.androidntg6poc D/ThriftGeneralService: client :thrift.transport.TTcpTransport@4608884, state :DISCONNECTED
2019-09-12 12:21:58.511 5040-6450/com.amg.androidntg6poc W/System.err: at thrift.TReactor.access$000(TReactor.java:30)
2019-09-12 12:21:58.511 5040-6450/com.amg.androidntg6poc W/System.err: at thrift.TReactor$1.run(TReactor.java:105)
2019-09-12 12:21:58.512 5040-6450/com.amg.androidntg6poc W/System.err: at java.lang.Thread.run(Thread.java:764)
2019-09-12 12:21:58.513 5040-6450/com.amg.androidntg6poc E/ThriftGeneralService: TException(E_TRANSPORT_CLOSED)
at thrift.TServiceBroker.transportStatusChanged(TServiceBroker.java:548)
at thrift.transport.TTransport$1.run(TTransport.java:258)
at thrift.TReactor.threadProc(TReactor.java:148)
at thrift.TReactor.access$000(TReactor.java:30)
at thrift.TReactor$1.run(TReactor.java:105)
at java.lang.Thread.run(Thread.java:764)
我们使用Conscrypt库来建立与 TCps 服务器的基于 PSK(预共享密钥)的通信,因此使用从 Conscrypt 提供的 pskKeyManagers 初始化的 sslContext。在具有大数据负载的 api 请求期间,我们收到上述错误。
此外,如果我们能获得任何使用 Conscrypt 进行 TLS 读/写通信的示例代码,那将会很有帮助。
在过去的 10 天里,我们一直在头疼。如果有人可以提供帮助,将不胜感激。
解决方案
推荐阅读
- c - 错误编译后C编程的错误消息中的“标签”是什么?
- python - Python父子特定类结构
- java - 奖励后如何自动关闭奖励广告[Android-Studio]
- html - 为什么位置:相对;似乎改变了z-index?
- javascript - 下拉菜单不会在第二次点击时关闭
- c++ - 使用 AES 和 XTR-DH Crypto++ 加密音频文件
- sql-server - 在 SQL 函数中比较日期失败
- javascript - 如何使用`cid`在Node js中嵌入带有覆盖文本CSS的图像
- mysql - 由mysql中的主键和唯一键组成的复合键?
- php - 将默认文件名从数据库更改为其当前值