从 Tomcat 9 到客户端的 Websocket 二进制消息拆分为 2 个或更多 tcp 数据包

Posted

技术标签:

【中文标题】从 Tomcat 9 到客户端的 Websocket 二进制消息拆分为 2 个或更多 tcp 数据包【英文标题】:Websocket Binary message from Tomcat 9 to client splitted to 2 or more tcp packets 【发布时间】:2016-08-26 11:01:52 【问题描述】:

我正在使用 Tomcat 9 和 Spring。

我的网络应用程序有一个 websocket 服务。

我的应用程序使用sendMessage 向客户端发送二进制消息:

org.springframework.web.socket.WebSocketSession.

我收集了wireshark的tcp数据包。我看到每个二进制 websocket 消息至少使用 2 个 TCP 数据包。

第一个数据包是标头,它很小。

似乎Java代码总是先发送头然后再发送数据。

如何解决此问题? 是 Spring 还是 Tomcat 的问题?

【问题讨论】:

我创建的 - 这是 Tomcat 的问题。 【参考方案1】:

根本问题是tomcat 实现中的一个错误。他们的 websocket 消息的 send 方法获取要发送的消息块列表,并通过它们对每个缓冲区调用 send() 和 flush() 进行迭代。当它们在单独的缓冲区中对标头进行编码时,标头和正文将因此以您正确识别的不同数据报的形式写入线路。我调查了这个问题,发现你试图向他们提交一个补丁,但由于额外的内存分配而被他们拒绝。

我向他们提出了另一个解决方案,他们只需在写入所有块后调用一次 flush(),而不是在每个块之间调用一次。这会导致消息的所有部分在可能的情况下进入单个数据报,而无需添加任何额外的内存分配。我在我的项目中测试了修复并验证了它,并且 tomcat 已经在他们的下一个版本中采用了它。

该修复将包含在 8.5.X 和 9.0 中。您必须升级 tomcat 才能解决此问题。

我在 tomcat 的 github 中提供了该问题的链接以供参考。

https://github.com/apache/tomcat85/commit/47c211eb3ee7f9be2df6c313fb65351feabd42d1

【讨论】:

以上是关于从 Tomcat 9 到客户端的 Websocket 二进制消息拆分为 2 个或更多 tcp 数据包的主要内容,如果未能解决你的问题,请参考以下文章

Tomcat启用GZIP压缩,提升web性能

Tomcat架构解析-----CoyoteHTTPAJPHTTP2等协议

Tomcat启用Gzip压缩,提升web性能

2019.9.2课程设计情况

Tomcat之Nginx+Tomcat实现负载均衡动静分离集群部署

tomcat的session问题