具有多个 ClientEndpoints 和二进制消息的 WebSocket
WebSocket with multiple ClientEndpoints and binary messages
概览:
我目前有一个功能齐全的移动应用程序,它通过 WebSockets 与 Windows 上的 Java 服务器 运行 通信。 ServerEndpoint 与 AWS 机器相距 运行。 Java 服务器是专用网络上的 ClientEndpoint 运行,在任何给定时间都可以有多个应用程序用户也是 ClientEndpoints。
我目前在来回发送字符串消息时一切正常,因为 ServerEndpoint 正在维护 Java 服务器会话以及移动应用程序会话。几乎所有通信都是通过移动应用程序发起的,此时 JSON 字符串被发送到 Java 服务器会话,以便能够维持哪个移动应用程序会话应该接收 return 消息。
我现在正在尝试实现能够以相同方式通过二进制消息将 PDF 文件从 Java 服务器发送到移动应用程序的功能。移动应用程序是使用 Codename One 开发的,它们不提供增加最大二进制消息大小的功能,因此我似乎将每个二进制消息限制为 8kb(8,192 字节)。这很好,因为我正在发送多条二进制消息并在移动应用程序中重建文件。
我目前在最简单的情况下工作,即一次只有一个移动应用程序用户请求 PDF 文件。
当前流量:
App A 向 ServerEndpoint 发送 JSON 消息,ServerEndpoint 然后将消息转发给 Java 服务器 A。Java 服务器 A 将 JSON 消息发送回将消息转发回 App A 的 ServerEndpoint。 JSON 对象包含将消息发送回的会话 ID。 ServerEndpoint 需要知道将来自 Java 服务器的消息发送到哪个 App Session。
当涉及到二进制消息时,应用程序 A 向 ServerEndpoint 发送一个字符串消息,然后将消息转发给 Java 服务器 A。 Java 服务器 A 现在需要将多个二进制消息发送回 ServerEndpoint,所有必须转发到应用程序 A 以正确重建文件。这是我不确定如何处理的部分。目前如果只有一个App session可以正常工作,但是如果多个App session同时请求文件,就无法正常工作了。
问题:
发送字符串消息时,很容易将回调移动应用程序会话 ID 作为 JSON 对象的一部分来回传递,以确保正确的移动应用程序会话获得响应。在发送二进制消息时,最好的方法是什么来保证如果用户 A 和 B 同时请求文件,则用户 A 获得请求的文件 he/she,用户 B 获得文件 he/she 要求?
您应该能够跟踪会话而无需传递会话 ID。例如,参见 this sample web service endpoint。
注意如何使用 @OnMessage
注释将 Session
对象作为第一个参数传递。
您可以使用它来了解您正在与谁通话。
另外一个小point/question。您的声明 "The mobile applications are developed using Codename One, and they do not provide the ability to increase the maximum binary message size," 似乎表明其他平台确实允许您在客户端上设置最大二进制大小。据我所知,这不是 WebSocket 规范的一部分,也没有被任何浏览器实现。还有哪些其他实现允许您设置最大大小?
编辑回应您对问题的细化:
有多种方法可以给这只猫剥皮。一种想法是您只需要将 "last mile" 分块(在中间人和客户之间)。由于中间人和终端服务器是 JavaEE 服务器,您可以控制缓冲区大小,并且可能一次发送完整文件(在合理范围内)。然后在中间服务器做chunking就可以了,它会知道他在和哪个client打交道。
另一种选择是创建您自己的伪协议。您正在返回字节数组,但您可以选择分配每个块的前 n 个字节以包含元数据,中间人将解析出这些元数据。此元数据可用于告诉中间人该块的目的地是哪个客户端。
压缩你要发送的文件并通过二进制发送,在服务器中解压缩以获取数据,我认为大小不是问题(虽然没有尝试过代号一)。如果是,那么您可以将结构化的二进制数据块发送到具有类型和序列号的 jason 对象,您可以检查这些数据以找到您正在发送的文件类型以及文件的块数。流程会像
get chuncks -> Json Object (Type="PDF", SerialNumber="1", Data="Binary data converted to String") -> 压缩 json 对象 -> 发送到服务器。在服务器中执行相反的操作。
概览:
我目前有一个功能齐全的移动应用程序,它通过 WebSockets 与 Windows 上的 Java 服务器 运行 通信。 ServerEndpoint 与 AWS 机器相距 运行。 Java 服务器是专用网络上的 ClientEndpoint 运行,在任何给定时间都可以有多个应用程序用户也是 ClientEndpoints。
我目前在来回发送字符串消息时一切正常,因为 ServerEndpoint 正在维护 Java 服务器会话以及移动应用程序会话。几乎所有通信都是通过移动应用程序发起的,此时 JSON 字符串被发送到 Java 服务器会话,以便能够维持哪个移动应用程序会话应该接收 return 消息。
我现在正在尝试实现能够以相同方式通过二进制消息将 PDF 文件从 Java 服务器发送到移动应用程序的功能。移动应用程序是使用 Codename One 开发的,它们不提供增加最大二进制消息大小的功能,因此我似乎将每个二进制消息限制为 8kb(8,192 字节)。这很好,因为我正在发送多条二进制消息并在移动应用程序中重建文件。
我目前在最简单的情况下工作,即一次只有一个移动应用程序用户请求 PDF 文件。
当前流量:
App A 向 ServerEndpoint 发送 JSON 消息,ServerEndpoint 然后将消息转发给 Java 服务器 A。Java 服务器 A 将 JSON 消息发送回将消息转发回 App A 的 ServerEndpoint。 JSON 对象包含将消息发送回的会话 ID。 ServerEndpoint 需要知道将来自 Java 服务器的消息发送到哪个 App Session。 当涉及到二进制消息时,应用程序 A 向 ServerEndpoint 发送一个字符串消息,然后将消息转发给 Java 服务器 A。 Java 服务器 A 现在需要将多个二进制消息发送回 ServerEndpoint,所有必须转发到应用程序 A 以正确重建文件。这是我不确定如何处理的部分。目前如果只有一个App session可以正常工作,但是如果多个App session同时请求文件,就无法正常工作了。
问题:
发送字符串消息时,很容易将回调移动应用程序会话 ID 作为 JSON 对象的一部分来回传递,以确保正确的移动应用程序会话获得响应。在发送二进制消息时,最好的方法是什么来保证如果用户 A 和 B 同时请求文件,则用户 A 获得请求的文件 he/she,用户 B 获得文件 he/she 要求?
您应该能够跟踪会话而无需传递会话 ID。例如,参见 this sample web service endpoint。
注意如何使用 @OnMessage
注释将 Session
对象作为第一个参数传递。
您可以使用它来了解您正在与谁通话。
另外一个小point/question。您的声明 "The mobile applications are developed using Codename One, and they do not provide the ability to increase the maximum binary message size," 似乎表明其他平台确实允许您在客户端上设置最大二进制大小。据我所知,这不是 WebSocket 规范的一部分,也没有被任何浏览器实现。还有哪些其他实现允许您设置最大大小?
编辑回应您对问题的细化:
有多种方法可以给这只猫剥皮。一种想法是您只需要将 "last mile" 分块(在中间人和客户之间)。由于中间人和终端服务器是 JavaEE 服务器,您可以控制缓冲区大小,并且可能一次发送完整文件(在合理范围内)。然后在中间服务器做chunking就可以了,它会知道他在和哪个client打交道。
另一种选择是创建您自己的伪协议。您正在返回字节数组,但您可以选择分配每个块的前 n 个字节以包含元数据,中间人将解析出这些元数据。此元数据可用于告诉中间人该块的目的地是哪个客户端。
压缩你要发送的文件并通过二进制发送,在服务器中解压缩以获取数据,我认为大小不是问题(虽然没有尝试过代号一)。如果是,那么您可以将结构化的二进制数据块发送到具有类型和序列号的 jason 对象,您可以检查这些数据以找到您正在发送的文件类型以及文件的块数。流程会像 get chuncks -> Json Object (Type="PDF", SerialNumber="1", Data="Binary data converted to String") -> 压缩 json 对象 -> 发送到服务器。在服务器中执行相反的操作。