核心是应用层添加消息边界以解决tcp无边界问题,推荐长度前缀法:消息头用2或4字节标明载荷长度,发送端先写长度再写内容,接收端需增量解析缓冲区,netty可用lengthfieldbasedframedecoder简化处理。

核心是让接收端能准确识别每条消息的起始和结束位置。TCP本身不带消息边界,必须在应用层加一层结构,把字节流还原成有边界的“包”。
选一种靠谱的消息边界方案
定长、分隔符、长度前缀这三种最常用,推荐长度前缀法:
- 定长消息:适合心跳、状态上报等固定格式数据。比如统一用64字节,不够就补空字节,接收方每次读满64字节再解析。缺点是浪费带宽,灵活性差。
-
分隔符法:用换行符
或控制字符0x02标记结尾。要注意真实数据里不能出现该分隔符,否则需转义(如把写成\n)或改用不可见字符。 -
长度前缀法(推荐):消息开头放2或4字节表示后续内容长度(大端序)。例如前4字节是
0x00 00 00 14(即20),后面紧跟着20字节有效载荷。这种设计容错强、扩展性好,Netty 默认也采用它。
发送端要严格按协议打包
不能直接 send 原始字符串,得先封装头部再发:
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 计算 payload 字节数(如 JSON 字符串 UTF-8 编码后长度)
- 用
ByteBuffer或DataOutputStream先写入长度字段(如putInt(len)) - 再写入 payload 字节数组
- 确保一次
channel.write()或socket.getOutputStream().write()发出完整头+体
接收端要增量解析缓冲区
尤其在 NIO 场景下,不能假设一次 read 就拿到整包:
- 维护一个接收缓冲区(如
ByteBuffer或byte[]动态扩容) - 每次从 channel 读到数据就追加进去
- 循环检查:如果已有数据 ≥ 头部长度(如4字节),就读出长度字段;再看是否 ≥ 总长度(头+体);满足就切出完整包,剩余字节 compact 或截取保留
- 不满足就等待下次 OP_READ 事件,绝不能 clear 缓冲区丢弃已读数据
用 Netty 可大幅简化逻辑
手动管理缓冲区容易出错,Netty 提供了成熟解码器:
- 加
LengthFieldBasedFrameDecoder(1024, 0, 4, 0, 4):最大帧长1024,长度字段从偏移0开始占4字节,不包含自身,读完跳过4字节 - 后续
ChannelInboundHandler的channelRead()收到的就是剥离头、无粘连、无截断的完整ByteBuf - 避免在业务 handler 中再操作原始 buffer,解码工作已由 pipeline 完成
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南










