3

私はサーバーを作成していますが、要件の 1 つは、クライアントから直接要求されたデータを持たずにクライアントにデータをプッシュできる必要があるということです。コンジットを使用していますが、これはコンジットの能力を超えているように感じます。私が遭遇した問題は、ソケットに利用可能なデータがあるかどうかを判断する方法がないように見え、データが利用可能になるまで await が実行をブロックすることです。次の機能があるとしましょう

getPacket :: Conduit ByteString IO ClientPacket --take a bytestring and yield a ClientPacket i.e. the ByteString deserialized into a sensible form
processPacket :: Conduit ClientPacket IO ServerPacket --take a ClientPacket and yield a ServerPacket i.e. a response to the client's request
putPacket :: Conduit ServerPacket IO ByteString --serialize the ServerPacket

次に、コンジットを Conduit.Network ライブラリのソースとシンクに接続します。

appSource appData $$ getPacket =$= processPacket =$= putPacket $= appSink appData

ここで、コンジットの外部からデータのソースを導入し、そのデータをコンジットに組み込みたいと考えています。たとえば、これがチャット サーバーの場合、外部データは他のクライアントから送信されたメッセージになります。問題は、この外部データをどこに導入しようとしても、await の呼び出しによってブロックされることです。基本的に、次のようなコードになります。

yield processOutsideData --deal with the outside data
data <- await            --await data from upstream

より多くの外部データが処理される唯一の方法は、上流のコンポーネントが何かを生成する場合ですが、上流はクライアントからデータを取得する場合にのみ生成されます。これはまさに私が避けようとしているものです。これを解決するために複数のスレッドと TChannel を使用しようとしましたが、appSource と appSink を同じスレッドで使用する必要があるようです。そうしないと、recv から無効なファイル記述子の例外が発生します (これは理にかなっています)。

ただし、ソケットのソースとシンクが同じスレッドで実行されている場合、await がブロックされているという問題が再び発生し、ソケットからデータが利用可能かどうかを確認する方法がありません。この時点で、コンジットで壁にぶつかったようです。

しかし、私はコンジットの使用を本当に楽しんでおり、引き続き使用したいと考えています。私の質問は次のとおりです。コンジットで達成しようとしていることを行う方法はありますか?

4

1 に答える 1