1.粘包问题的出现,一般是发送端的发送速度大于接收端,有些时候为了处理方便,经常省去了定义信息头部,
导致接收端不知道已经读取到了什么地方,这个时候如果不定义头部,就会出现很多包粘在一起。
解决方法:
发送端:可先发送一个头部信息,这个头部信息的内容可以自己定义(一般的做法头部信息格式如下: )
类型(表明是哪一个类型数据包的头部的) | 协议版本号 | 信息长度(告诉接收端,需要读取多少个字节的数据) |
客户端发送信息:
/** * 发送消息 * * @param message */ public void sendMessage( String message) { if (mChatService.getState() != BluetoothChatService.STATE_CONNECTED) { Toast.makeText(this.context, "没有连接上", Toast.LENGTH_SHORT).show(); return; } if (message.length() > 0) { int len = message.getBytes().length; byte[] head = ArrayUtils.intToBytes(len); mChatService.write(head); byte[] send = message.getBytes(); mChatService.write(send); mOutStringBuffer.setLength(0); } }
客户端工具类:
package com.example.baize.utils; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; /** * Created by lxb on 2017/2/23. */ public class ArrayUtils { /** * 获取两个数据的并集 * * @param arr1 * @param arr2 * @return */ public static String[] union(String[] arr1, String[] arr2) { Set<String> set = new HashSet<>(); for (String str : arr1) { set.add(str); } for (String str : arr2) { set.add(str); } String[] result = {}; return set.toArray(result); } /** * 求两个数组的差集 * * @param arr1 * @param arr2 * @return */ public static String[] minus(String[] arr1, String[] arr2) { LinkedList<String> list = new LinkedList<>(); LinkedList<String> history = new LinkedList<>(); String[] longerArr = arr1; String[] shorterArr = arr2; if (arr1.length > arr2.length) { //找出较长的数组来减较短的数组 longerArr = arr2; shorterArr = arr1; } for (String str : longerArr) { if (!list.contains(str)) { list.add(str); } } for (String str : shorterArr) { if (list.contains(str)) { history.add(str); list.remove(str); } else { if (!history.contains(str)) { list.add(str); } } } String[] result = {}; return list.toArray(result); } public static byte[] intToBytes( int value ) { byte[] src = new byte[4]; src[3] = (byte) ((value>>24) & 0xFF); src[2] = (byte) ((value>>16) & 0xFF); src[1] = (byte) ((value>>8) & 0xFF); src[0] = (byte) (value & 0xFF); return src; } }
服务端解析数据方法:
private class ConnectedThread extends Thread { private final BluetoothSocket mmSocket; private final InputStream mmInStream; private final OutputStream mmOutStream; public ConnectedThread(BluetoothSocket socket) { mmSocket = socket; InputStream tmpIn = null; OutputStream tmpOut = null; try { tmpIn = socket.getInputStream(); tmpOut = socket.getOutputStream(); } catch (IOException e) { Log.e(TAG, "temp sockets not created", e); } mmInStream = tmpIn; mmOutStream = tmpOut; } public void run() { Log.i(TAG, "BEGIN mConnectedThread"); byte[] buffer = new byte[1024]; int bytes; while (read(mmInStream, buffer, 4) != 0) { /*try { bytes = mmInStream.read(buffer); mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, bytes, -1, buffer).sendToTarget(); } catch (IOException e) { Log.e(TAG, "disconnected", e); connectionLost(); break; } */ //read headlen //read(mmInStream, buffer, 4); //read data String readMessage = new String(buffer, 0, ArrayUtils.byteArray2Int(buffer)); int len = readMessage.length(); byte[] dataBufer = new byte[len]; read(mmInStream, dataBufer, len); mHandler.obtainMessage(BluetoothChat.MESSAGE_READ, len, -1, dataBufer).sendToTarget(); } } /** * Write to the connected OutStream. * * @param buffer The bytes to write */ public void write(byte[] buffer) { try { mmOutStream.write(buffer); mHandler.obtainMessage(BluetoothChat.MESSAGE_WRITE, -1, -1, buffer).sendToTarget(); } catch (IOException e) { Log.e(TAG, "Exception during write", e); } } public void cancel() { try { mmSocket.close(); } catch (IOException e) { Log.e(TAG, "close() of connect socket failed", e); } } /** * 读取消息 * * @param inputStreams * @param buffer * @param len * @return */ private int read(InputStream inputStreams, byte[] buffer, int len) { int total = 0; int curLen = 0; while (total != len) { try { curLen = inputStreams.read(buffer, total, len - total); total += curLen; } catch (IOException e) { connectionLost(); System.out.println("428--------------------read data:" + e.toString()); break; } } return total; } }
服务端工具类:
package com.example.lxb.btserver.utils; /** * 数组转换工具 * Created by lxb on 2017/2/15. */ public class ArrayUtils { /** * int[] -> Integer[] * @param intArray * @return */ public static Integer[] int2Integer(int[] intArray) { Integer[] result = new Integer[intArray.length]; for (int i = 0; i < intArray.length; i++) { result[i] = Integer.valueOf(intArray[i]); } return result; } /** * Integer[] -> int[] * * @param IntegerArray * @return */ public static int[] Integer2int(Integer[] IntegerArray) { int[] result = new int[IntegerArray.length]; for (int i = 0; i < IntegerArray.length; i++) { result[i] = IntegerArray[i].intValue(); } return result; } /** * String[] ->int[] * @param str * @return */ public static int[] string2Int(String[] str){ int[] result = new int[str.length]; for (int i = 0; i < str.length; i++) { result[i] = Integer.parseInt(str[i]); } return result; } public static int byteArray2Int(byte[] ary) { int value; value = (int) ((ary[0]&0xFF) | ((ary[1]<<8) & 0xFF00) | ((ary[2]<<16)& 0xFF0000) | ((ary[3]<<24) & 0xFF000000)); return value; } public static byte[] int2ByteArray(int a) { return new byte[] { (byte) ((a >> 24) & 0xFF), (byte) ((a >> 16) & 0xFF), (byte) ((a >> 8) & 0xFF), (byte) (a & 0xFF) }; } }