2012-02-13 21 views
1

私は2つのアプリケーションをTCP上でJSONベースのメッセージと通信させようとしています。そのために私はJacksonライブラリ(1.9.4)を使用しています。クライアント側はソケットを開き、サーバーからのすべての着信メッセージをリッスンします。Json over Jackson with

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) 
} 

したがって、メッセージが解析されて処理されるまで、読み取りがブロックされて処理されるまで待機します。 私の問題は、時には読むときにいくつかのメッセージがスキップされることです。サーバーがmsg1msg、およびmsg3を送信する場合は、msg2が失われても問題ありませんが、msg3が問題なく読み取られます。

これを奇妙にするには、これは常に起こるわけではなく、約50%です。クライアントとサーバーの両方がスレッド化されているため、他の誰もソケットにアクセスできません。そして、メッセージが到着したという事実を知り、ncでクライアントをシミュレートしようとしました。着信メッセージは常に正しいので、読んでいると分かります。

TCPソケットなので、到着順序が保証されているので、ObjectReaderは何も例外を投げずに静かに廃棄していると思われます。

誰かが何が起こっているのかという手がかりを持っていますか?どんな考えも歓迎です! :)

+0

「リーダー」とは何ですか?また、「readValue()」とは何ですか? –

+0

ReaderはJacksonライブラリーのObjectReaderです。着信メッセージを読み込んで解析する必要があります(これはreadValue()メソッドで行われます) – Chirlo

答えて

1

1つの提案:Readerを作成せず、そのままInputStreamを渡してください。 Readerを構築することには利点はなく、やや遅くなります。それが問題自体に役立つかどうかはわかりませんが、ジャクソンはそれをする必要があるときには読書を確実にブロックします。

しかし、基本的なJsonParserはバッファリングされるため(パフォーマンス上の理由から)、バッファリングされたデータは返されません(入力ストリームまたはリーダーにデータを返す方法がないため)。

JsonParserは、このような余分なバッファされたデータにアクセスするためのメソッドを持っていますが、この問題を解決するための最も簡単な方法は、明示的にJsonParserJsonFactoryを経由して)作成し、ObjectReaderにそれを渡し、1を作成するためにObjectReaderを聞かないことです。このようにして、同じパーサーが使用され、それがバッファリングするデータが使用されます。これは、パーサーの作成オーバーヘッドがないため、やや高速かもしれません。

さらにもう1つの方法:ObjectReader.readValues()(そこに-sを書きます)をチェックしてください。これは便利で、パーサーを手動で作成して渡すのと同じように動作します。

+0

私があなたがStaxManであることを理解するまでは、問題を解決したと思われるJsonParserを再利用しました。ありがとうございました – Chirlo

+0

クール、問題ありません!たぶん私は名前を '@ MrJackson'に変更するべきでしょう:-) – StaxMan

0

種類が見つかりました。

readValue()メソッドは、Readerという完全なJSONメッセージを受け取ったアンダーレイの各呼び出しで正しく動作します。

私はソケットから読み込んでいたので、read()メソッドが完全なメッセージよりも少なく返され、ObjectReaderが正しく処理できないことがありました。これは奇妙です。ReaderBasedParserクラスは読み込み前にwhile()というクラスを持っているので、メッセージ全体があるときだけ返るべきです。

私は時間があれば詳しく見ていきます。