Netty(三) 什么是 TCP 拆、粘包?如何解决? (3)

同样的提供了一个接口向服务端发送消息,当服务端收到了一个特殊指令时也会向客户端返回内容:

@Override protected void channelRead0(ChannelHandlerContext ctx, BaseRequestProto.RequestProtocol msg) throws Exception { LOGGER.info("收到msg={}", msg.getReqMsg()); if (999 == msg.getRequestId()){ BaseResponseProto.ResponseProtocol responseProtocol = BaseResponseProto.ResponseProtocol.newBuilder() .setResponseId(1000) .setResMsg("服务端响应") .build(); ctx.writeAndFlush(responseProtocol) ; } }

在 swagger 中调用相关接口:

Netty(三) 什么是 TCP 拆、粘包?如何解决?

在日志可以看到服务端收到了消息,同时客户端也收到了返回:

Netty(三) 什么是 TCP 拆、粘包?如何解决?

Netty(三) 什么是 TCP 拆、粘包?如何解决?

虽说 Netty 封装了 Google Protobuf 相关的编解码工具,其实查看它的编码工具就会发现也是利用上文提到的 api 实现的。

Netty(三) 什么是 TCP 拆、粘包?如何解决?

Protocol 拆、粘包

Google Protocol 的使用确实非常简单,但还是有值的注意的地方,比如它依然会有拆、粘包问题。

不妨模拟一下:

Netty(三) 什么是 TCP 拆、粘包?如何解决?

连续发送 100 次消息看服务端收到的怎么样:

Netty(三) 什么是 TCP 拆、粘包?如何解决?

会发现服务端在解码的时候报错,其实就是被拆、粘包了。

这点 Netty 自然也考虑到了,所以已经提供了相关的工具。

//拆包解码 .addLast(new ProtobufVarint32FrameDecoder()) .addLast(new ProtobufVarint32LengthFieldPrepender())

只需要在服务端和客户端加上这两个编解码工具即可,再来发送一百次试试。

查看日志发现没有出现一次异常,100 条信息全部都接收到了。

Netty(三) 什么是 TCP 拆、粘包?如何解决?

这个编解码工具可以简单理解为是在消息体中加了一个 32 位长度的整形字段,用于表明当前消息长度。

总结

网络这块同样是计算机的基础,由于近期在做相关的工作所以接触的比较多,也算是给大学补课了。

后面会接着更新 Netty 相关的内容,最后会产出一个高性能的 HTTP 以及 RPC 框架,敬请期待。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wsfsww.html