0%

java |bytebuffer 黏包和半包

黏包和半包讲解。

引入自写的方法类。

下载 JAVA 文件

netty 包

1
2
3
4
5
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.86.Final</version>
</dependency>

现象

  • 黏包
    • 字段 「通过 \n 进行数据分隔」
      • How are you?\n
      • I am rhino\n
    • 网络传输中变成了下面两个 ByteBuffer
      • How are
      • you?\n I am
      • rhino\n
  • 半包
    • 服务器缓冲区大小限制

解决

将混乱的数据恢复成 \n 分隔的数据。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package com.redisc;

import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;

import static com.redisc.ByteBufferUtil.debugAll;

@Slf4j(topic = "c.Test")
public class Run {

public static void main(String[] args) {
ByteBuffer source = ByteBuffer.allocate(32);

source.put("Hello world\nI'm rhino\nH".getBytes());
split(source);
source.put("ow are you?\n".getBytes());
split(source);
}

private static void split(ByteBuffer source) {
// 读模式
source.flip();
for (int i = 0; i < source.limit(); i++) {
if (source.get(i) == '\n') {
int length = i + 1 - source.position();// 一条消息的长度
ByteBuffer target = ByteBuffer.allocate(length);
// 从 source 读,向 target 写
for (int j = 0; j < length; j++) {
target.put(source.get());
}
debugAll(target);
}
}
// 写模式
source.compact();
}
}

输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
+--------+-------------------- all ------------------------+----------------+
position: [12], limit: [12]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 65 6c 6c 6f 20 77 6f 72 6c 64 0a |Hello world. |
+--------+-------------------------------------------------+----------------+
+--------+-------------------- all ------------------------+----------------+
position: [10], limit: [10]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 49 27 6d 20 72 68 69 6e 6f 0a |I'm rhino. |
+--------+-------------------------------------------------+----------------+
+--------+-------------------- all ------------------------+----------------+
position: [13], limit: [13]
+-------------------------------------------------+
| 0 1 2 3 4 5 6 7 8 9 a b c d e f |
+--------+-------------------------------------------------+----------------+
|00000000| 48 6f 77 20 61 72 65 20 79 6f 75 3f 0a |How are you?. |
+--------+-------------------------------------------------+----------------+
请我喝杯咖啡吧~