记录一下项目中SSLSocket的坑
private void readStreamOld(byte[] out) throws IOException
{
byte[] reading = null;
ByteArrayOutputStream cache = new ByteArrayOutputStream();
int total = out.length;
while (total > 0) {
int amount = total;
int available = in.available();
if (amount > available) {
amount = available;
}
reading = new byte[amount];
in.read(reading);
cache.write(reading);
total -= amount;
}
new java.io.ByteArrayInputStream(cache.toByteArray()).read(out);
}
上面这段代码是服务端读取输入流的代码,当使用socket通信时,不会出错。
但是当使用sslsocket通信时,就会阻塞,最终导致客户端产生以下错误:
经过debug发现当使用sslsocket通信时,当握手成功之后, client向server端先发送第一段信息后,in.available() = 0,导致server逻辑死循环导致阻塞。
网上查询资料翻译可知:
InputSteam的available()方法的功能是返回该输入流可以在不阻塞的情况下读取的字节数。网络流和文件流之间区别的关键在于它是否被“阻止”。读取网络套接字流时,如果没有内容,read()方法将被阻止,因此从套接字初始化的可用输入流也为零。因此,在使用前必须先读取一个字节,以便可用字节数等于可用字节数+1。但是读取文件时,read()通常不会被阻止,因为文件流的可用字节数为available=file。length(),创建文件对象时,文件的内容长度是已知的。因此,在调用网络流(socket)的available()方法之前,必须记住首先调用read()方法,以避免获取0的错误情况。
//Store the received data in the byte array bytes
int firstByte = inputStream.read();
int length = inputStream.available();
byte[] bytes = new byte[length+1];
bytes[0] = (byte)firstByte;
inputStream.read(bytes,1,length);
上述报错方法改为
private void readStream(byte[] out) throws IOException
{
byte[] reading = null;
ByteArrayOutputStream cache = new ByteArrayOutputStream();
int total = out.length;
while (total > 0) {
int amount = total;
int firstbyte = in.read();
int available = in.available();
if (amount > available+1) {
amount = available+1;
}
reading = new byte[amount];
reading[0] = (byte)firstbyte;
in.read(reading,1,amount-1);
cache.write(reading);
total -= amount;
}
new java.io.ByteArrayInputStream(cache.toByteArray()).read(out);
}
问题就解决了。