私はedge-triggeredモードでepollを使用し、ノンブロッキングソケット操作を行うTCP/IPサーバーアプリケーションを実装しています。クライアントはepollなしで単純なブロッキング操作を使用しています。Cソケットアトミック非ブロッキングリード
「アトミックリード」をサーバー側でどのように実装できるかわかりません。
- クライアントとサーバーの両方で64Kバッファーを使用しています。「原子読み取り」の意味を説明するには、次の例を参照してください。 (アプリケーションレベルでは、カーネルレベルのソケットバッファを変更しません)
- クライアントは、1回の書き込み操作で12Kデータを書き込みます。
- サーバーがそれを読み取ります。この場合、バッファが同じ場合は常に12K全体を読み込みます。だから、半分しか読めない。これが私が「原子」と呼ぶものです。
しかし、epollを+非ブロック操作の場合にこれが起こることができます:
- クライアントとサーバの両方が64Kバッファを使用しています。 (アプリケーションレベルでは、カーネルレベルのソケットバッファを変更しません)
- クライアントは、1回の書き込み操作で12Kデータを書き込みます。
- 6Kは
- ファイルディスクリプタデータは、アプリケーションが非ブロッキング操作を使用してバッファに6Kを読み取るソケット
- に到着したアプリケーションに指示し、サーバーに到達します。
- 読み取りを繰り返すと、EAGAIN/EWOULDBLOCKを返します。
この場合、読み取りは「アトミック」ではありません。データが単一の書き込み操作で書き込まれたとき、読み取りは全体を1つの部分に戻すことは保証されていません。
データが部分的なときを知ることはできますか? 1つの解決策は、常にデータサイズを最初に追加することです。あるいは、別の方法では接続をいつでも閉じて再オープンすることができますが、私はこれらをやりたいとは思いません。カーネルは、ブロッキング操作のアトミック性を保証するため、「パッケージ」(BTWと呼ばれるユニットはどのように到着しましたか)が到着しました。
多くの感謝!
あなたは、一般的に*ループ*内のすべてのI/Oを書いて、あなた自身のバッファを維持する必要があります。 –
ソケット上の 'read'呼び出しが' 0'を返さなかった場合、イベントループで取り込むことができるより多くのデータが存在することが期待できます。 – jacob
バイナリ送信では、送信の開始や送信の終了などの区切り文字を追加するのが一般的です。テキスト送信では、構文チェックはあなたの友人です。 json文字列を送信する場合は、json文字列を解析して、完全かどうかを判断できます。 – alvits