/** * 黏包、半包 */ private static void buffExample2() { /* 网络上传输多条数据给服务器,数据之间使用 \n 分隔。 但由于某种原因(多条数据合并发送会快)这些数据在接收时,被进行了重新组合,例如3条原始数据: Hello world!\n I'm Lihua.\n How are you?\n 变成了2个 ByteBuffer,一个叫黏包,一个叫半包: Hello world!\nI'm Lihua.\nHow a re you?\n 如何使用代码将错乱的数据恢复成原来使用 \n 分割的样子 */ // 模拟处理黏包、半包现象 ByteBuffer buf1 = ByteBuffer.allocate(50); // 接受到网络传输第一条消息 buf1.put("Hello world!\nI'm Lihua.\nHow a".getBytes(StandardCharsets.UTF_8)); System.out.println("第一次调用:"); msgSplit(buf1); // 调用处理方法 buf1.put("re you?\n".getBytes(StandardCharsets.UTF_8)); // 接受到网络传输第二条消息 System.out.println("第二次调用:"); msgSplit(buf1); // 调用处理方法 } private static void msgSplit(ByteBuffer buff) { buff.flip(); // 切换成读模式,为下面的读取字符做准备 for (int i = 0; i < buff.limit(); i++) { if (buff.get(i) == '\n') { // 判断 \n 所在位置 // 计算将要截取字符串的长度,包含 \n 符号在内 int len = i + 1 - buff.position(); // buff.position() 指针的位置 System.out.println("position:" + buff.position() + ",limit:" + buff.limit() + ",len:" + len); ByteBuffer readBuff = ByteBuffer.allocate(len); for (int j = 0; j < len; j++) { readBuff.put(buff.get()); } readBuff.flip(); System.out.println("读取到的消息:" + StandardCharsets.UTF_8.decode(readBuff)); } } System.out.println("切换成写模式!"); buff.compact(); // 切换成写模式,为后面消息写入做准备 }