我不知道为什么,但有一半通过ssl的站点在读取过程中会出现buffer_underflow。
当我把我的程序链接起来连续调用不同的ssl站点时,它对一半的链接都不起作用,但如果我逐个调用,它们就会起作用。例如,我使用Chrome的开发工具调用https://www.facebook.com在我的nexus 7平板电脑上。当我看到请求时,调用的链接是:
- https://www.facebook.com/
- https://fbstatic-a.akamaihd.net/rsrc.php/v2/y7/r/Zj_YpNlIRKt.css
- https://fbstatic-a.akamaihd.net/rsrc.php/v2/yI/r/5EMLHs-7t29.css等等
- 。。。(约26个链接)
如果我将它们链接在一起(以模拟对https://www.facebook.com从浏览器),我得到一半的链接得到缓冲区下溢,直到最终我不得不关闭它们的连接(读取0字节)。然而,如果我一个接一个地给他们打分,他们总是很好的。这是我的阅读代码:
public int readSSLFrom(SelectionKey key, SecureIO session) throws IOException{
int result = 0;
String TAG = "readSSLFrom";
Log.i(TAG,"Hanshake status: "+session.sslEngine.getHandshakeStatus().toString());
synchronized (buffer){
ByteBuffer sslIn = ByteBuffer.allocate(session.getApplicationSizeBuffer());
ByteBuffer tmp = ByteBuffer.allocate(session.getApplicationSizeBuffer());
ReadableByteChannel channel = (ReadableByteChannel) key.channel();
if (buffer.remaining() < session.getPacketBufferSize()){
increaseSize(session.getPacketBufferSize());
}
int read = 0;
while (((read = channel.read(sslIn)) > 0) &&
buffer.remaining() >= session.getApplicationSizeBuffer()){
if (read < 0){
session.sslEngine.closeInbound();
return -1;
}
inner: while (sslIn.position() > 0){
sslIn.flip();
tmp.clear();
SSLEngineResult res = session.sslEngine.unwrap(sslIn, tmp);
result = result + res.bytesProduced();
sslIn.compact();
tmp.flip();
if (tmp.hasRemaining()){
buffer.put(tmp);
}
switch (res.getStatus()){
case BUFFER_OVERFLOW:
Log.i(TAG,"Buffer overflow");
throw new Error();
case BUFFER_UNDERFLOW:
Log.i(TAG,"Buffer underflow");
if (session.getPacketBufferSize() > tmp.capacity()){
Log.i(TAG,"increasing capacity");
ByteBuffer b = ByteBuffer.allocate(session.getPacketBufferSize());
sslIn.flip();
b.put(sslIn);
sslIn = b;
}
break inner;
case CLOSED:
Log.i(TAG,"Closed");
if (sslIn.position() == 0){
break inner;
} else{
return -1;
}
case OK:
Log.i(TAG,"OK");
session.checkHandshake(key);
break;
default:
break;
}
}
}
if (read < 0){
//session.sslEngine.closeInbound();
return -1;
}
}
dataEnd = buffer.position();
return result;
}
谢谢。
缓冲区下溢在展开过程中是可以接受的,并且经常发生。当您有一个部分TLS记录(<16KB)时,就会发生这种情况。这可能发生在两种情况下:1)当您的数据量小于16KB时,因此打开包装时不会得到任何结果-只需缓存所有这些数据,然后等待剩余数据到达即可打开包装。2)当数据量大于16KB但最后一个TLS数据包未完成时,例如20KB或36KB。在这种情况下,第一个16KB/32KB将在拆封过程中给您一个结果,您需要缓存剩余的4KB,然后等待完成此TLS数据包的12KB的剩余部分,然后才能拆封。
我希望这有帮助,试试我的代码,看看它是否适合你。
很抱歉,这不适合评论,所以我改为回答。