java - 与 Jackson 通过 Socket 进行 Json

标签 java json sockets jackson

我正在尝试让两个应用程序通过 TCP 使用基于 JSON 的消息进行通信。为此,我使用 Jackson 库(1.9.4)。客户端只需打开一个套接字,然后监听来自服务器的所有传入消息。它看起来像这样:

ObjectMapper mapper = new ObjectMapper().configure(
            Feature.AUTO_CLOSE_SOURCE, false);
final ObjectReader reader = mapper.reader(Message.class);

Socket s = new Socket("192.168.1.102", 32000);
final Reader in = new InputStreamReader(socket.getInputStream());
while (true) {
    Message message = reader.readValue(in);
    process(message)
}

因此,读取器会阻塞并等待,直到消息完成才能解析并处理它。 我的问题是,有时阅读时会跳过一些消息。如果服务器发送 msg1msgmsg3,可能 msg2 丢失,但 msg3 读取没有问题。

更奇怪的是,这种情况并不总是发生,但大约有 50% 发生。客户端和服务器都是单线程的,因此没有其他人可以访问套接字。我知道消息到达的事实,我尝试用 nc 模拟客户端,并且传入的消息总是正确的,所以我知道这是在阅读时。

由于它是一个 TCP 套接字,因此它们到达的顺序是有保证的,所以我怀疑 ObjectReader 正在默默地丢弃一些东西而不抛出任何异常。

有人知道会发生什么吗?欢迎任何想法! :)

最佳答案

一个建议:不要创建 Reader,只需按原样传递 InputStream 即可。构建Reader没有任何好处,而且速度稍微慢一些。不确定这是否有助于解决问题本身,但 jackson 肯定会在必要时阻止读取。

但是,最有可能发生的情况是,由于底层 JsonParser 会进行缓冲(出于性能原因),因此不会返回缓冲的数据(因为无法将数据“返回”到输入流或读取器)。

JsonParser 确实有方法来访问此类额外的缓冲数据,但解决此问题的最简单方法是显式创建 JsonParser(通过 JsonFactory),并将其传递给 ObjectReader,而不是要求 ObjectReader 创建一个。这样,将使用相同的解析器,并使用它缓冲的数据。这也可能会稍微快一些,因为没有每个解析器的创建开销。

还有一种替代方法:查看 ObjectReader.readValues() (请注意其中的 -s),这很方便,并且与手动创建和传递解析器的方式几乎相同。

关于java - 与 Jackson 通过 Socket 进行 Json,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9267669/

相关文章:

java - 带有 List<String> 的原始类型给出编译错误

java - 如何在javax.ws.rs.client中为客户端重用java中的tcp session

json - 使用 golang 从 http 网络服务器中提取特定的和最新的数据

python - Python:如何从4字节字节数组中获取4字节大小的整数?

Java 2D PNG : Calculate Dimension

java - 从文件或字符串变量读取有什么区别

android - 基于 JSON 数据的通知 - Android Studio

c# - ASP.NET Web API 本地主机 :xxxx/api/product defaults to Home Page and not JSON data(orXML)

java - 带有多线程示例的 Spring 集成 TCP 服务器

c++ - 套接字不发送所有二进制数据