Connection reset :readline 引起的socket讀取異常


在和銀聯進行聯機交易時,突然出現無法讀取響應的情況;

報錯信息如下:

java.net.SocketException: Connection reset
at java.net.SocketInputStream.read(SocketInputStream.java:196)
at java.net.SocketInputStream.read(SocketInputStream.java:122)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)

 

Connection reset是服務器關閉了連接,一直認為是服務器錯誤導致的;

后來發現是代碼中使用了 socket的readline方法導致的;

原代碼如下:

  socket = new Socket(this.serverHost, this.serverPort);
  socket.setSoTimeout(timeOut);
  writer = new PrintWriter(socket.getOutputStream());
  log.info("准備發送服務端數據: " + msg);
  writer.println(msg);
  writer.flush();
  log.info("請求完成, 准備接收返回");
  reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), Encoding.GBK));
  String resp = reader.readline();
  ......

readline()方法會讀到流結束或者\n的時候返回。

讀取文件時,文件結尾就代表流結束,但是socket沒有關閉的話就不會結束這個流。服務器在消息的結尾如果沒有發送換行符 \n 的話,也不會讀取結束;

 

解決方案:每次讀取的報文大小由報文頭決定

 

  socket = new Socket(this.serverHost, this.serverPort);
  socket.setSoTimeout(timeOut);
  writer = new PrintWriter(socket.getOutputStream());
  log.info("准備發送服務端數據: " + msg);
  writer.println(msg);
  writer.flush();
  log.info("請求完成, 准備接收返回");
  reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), Encoding.GBK));
  char[] rDataLen = new char[4];
  reader.read(rDataLen, 0, 4);
  int lenth = Integer.parseInt(new String(rDataLen));
  char[] rContentTxt = new char[lenth];
  reader.read(rContentTxt, 0, lenth);
  String response = new String(rDataLen) + new String(rContentTxt);

至此,解決了這個問題;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM