记录一下项目中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);
   }

 问题就解决了。

Logo

技术共进,成长同行——讯飞AI开发者社区

更多推荐