一、問題描述:
socket通信中經常會遇到返回報文接收不全甚至完全沒有接收到的問題。
二、解決方案:
發送方在報文頭用固定長度的字節聲明該報文正文長度,注意這裏的報文正文不包括表示報文長度的字符串本身。接收方在接收報文時先按約定讀取報文長度的聲明,轉換爲數字類型,再根據該長度讀取報文內容,以避免漏讀的情況。
三、代碼實現(Java):
以8位長度的報文頭表示報文正文長度爲例,此時報文接收方的示例代碼如下:
import java.io.*;
import java.net.Socket;
/**
* Created by linghan on 2018/12/20.
*/
public class SocketClient{
public static String ReceiveXml(){
DataOutputStream out = null;
Socket socket = null;
BufferedWriter bufferedWriter = null;
String returnXml="";
try {
socket = new Socket("localhost", 9999);
int headLen = 8; //約定的報文頭長度
char [] xmlLen = new char[headLen];
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
int curHeadLength = 0;
while(curHeadLength < headLen){
int readLen = bufferedReader.read(xmlLen,curHeadLength,headLen-curHeadLength);
//注意這裏的判斷不能省略 因爲當報文結束時read()方法返回值爲-1 此時如果我們讀到的結束符 , readLen 就會被賦值爲-1 ,那麼循環就會繼續,結果就會造成xmlLen數組的下標越界,自然會得到錯誤的結果
if(readLen < 0){
break;
}
curHeadLength += readLen;
}
int bodyLength = Integer.parseInt(new String(xmlLen));
char [] xml = new char[bodyLength];
int curBodyLength = 0;
while(curBodyLength < bodyLength){
int readLen2 = bufferedReader.read(xml,curBodyLength,bodyLength-curBodyLength);
if(readLen2 < 0){
break;
}
curBodyLength += readLen2;
}
returnXml = new String(xml);
} catch (IOException e) {
e.printStackTrace();
} catch (NumberFormatException e){
e.printStackTrace();
}finally{
try {
socket.close();
out.close();
} catch (IOException e1) {
e1.printStackTrace();
}
}
return returnXml;
}
}
四、read(char cbuf[], int off, int len)方法詳解:
該方法的作用就是從接收內容的第off個字符開始,最多讀取len個長度存進cbuf這個數組中,注意這裏是以追加的形式存到數組裏的。爲什麼len是最多讀取的意思呢,當可供讀取的長度大於等於len的時候,直接讀取len個,當可供讀取的長度不足len的時候,有多少讀多少。
測試代碼:
//報文發送方發送如下內容
String returnxml = "1AAAAAAAAA2BBBBBBBBB3CCCCCCCCC4DDDDDDDDD5EEEEEEEEE";
bufferedWriter = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
bufferedWriter.write(returnxml);
bufferedWriter.flush();
socket.shutdownOutput();
//報文接收方每次讀取10位長度
int headLen = 50;
char[] xml = new char[headLen];
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
int curHeadLength = 0;
while (curHeadLength < headLen) {
int readLen = bufferedReader.read(xml, curHeadLength,10);
System.out.println("讀取長度:" + readLen + " 字節數組的內容:" + new String(xml));
if (readLen < 0) {
break;
}
curHeadLength += readLen;
}
System.out.println("數組的最終內容:" + new String(xml));
接收方運行結果:
此結果可證明read()方法中的數組參數,是以追加的方式被賦值的。
轉載請註明出處,如有錯誤歡迎指正!