最近項目遇到socket服務端接收報文不全的問題,與其客戶端約定的是報文長度+報文體。然而當客戶端數據量大的時候,用分包發送,導致服務端報文日志接收不完整,於是想着先讀出包體長度,再讀出包體,不夠就一直讀,部分代碼如下:
InputStream reader = socket.getInputStream(); if (bytes.length < PACKET_HEAD_LENGTH) { byte[] head = new byte[PACKET_HEAD_LENGTH - bytes.length]; int couter = reader.read(head); if (couter < 0) { continue; } bytes = mergebyte(bytes, head, 0, couter); if (couter < PACKET_HEAD_LENGTH) { continue; } } // 取7長度的字節子數組作為報文長度 byte[] temp = new byte[0]; temp = mergebyte(temp, bytes, 0, PACKET_HEAD_LENGTH); String templength = new String(temp); int bodylength = Integer.parseInt(templength);//包體長度 if (bytes.length - PACKET_HEAD_LENGTH < bodylength) {//不夠一個包 byte[] body = new byte[bodylength + PACKET_HEAD_LENGTH - bytes.length];//剩下應該讀的字節(湊一個包) int couter = reader.read(body); if (couter < 0) { continue; } bytes = mergebyte(bytes, body, 0, couter); if (couter < body.length) { continue; } } byte[] body = new byte[0]; body = mergebyte(body, bytes, PACKET_HEAD_LENGTH, bytes.length); count++; System.out.println("server receive body: " + count+new String(body)); bytes = new byte[0];
mergebyte方法如下:
public byte[] mergebyte(byte[] a, byte[] b, int begin, int end) { byte[] add = new byte[a.length + end - begin]; int i = 0; for (i = 0; i < a.length; i++) { add[i] = a[i]; } for (int k = begin; k < end; k++, i++) { add[i] = b[k]; } return add; }
這樣server端接收到的都是完整的包。