2016-09-08 4 views
0

私はedge-triggeredモードでepollを使用し、ノンブロッキングソケット操作を行うTCP/IPサーバーアプリケーションを実装しています。クライアントはepollなしで単純なブロッキング操作を使用しています。Cソケットアトミック非ブロッキングリード

「アトミックリード」をサーバー側でどのように実装できるかわかりません。

  • クライアントとサーバーの両方で64Kバッファーを使用しています。「原子読み取り」の意味を説明するには、次の例を参照してください。 (アプリケーションレベルでは、カーネルレベルのソケットバッファを変更しません)
  • クライアントは、1回の書き込み操作で12Kデータを書き込みます。
  • サーバーがそれを読み取ります。この場合、バッファが同じ場合は常に12K全体を読み込みます。だから、半分しか読めない。これが私が「原子」と呼ぶものです。

しかし、epollを+非ブロック操作の場合にこれが起こることができます:

  • クライアントとサーバの両方が64Kバッファを使用しています。 (アプリケーションレベルでは、カーネルレベルのソケットバッファを変更しません)
  • クライアントは、1回の書き込み操作で12Kデータを書き込みます。
  • 6Kは
  • ファイルディスクリプタデータは、アプリケーションが非ブロッキング操作を使用してバッファに6Kを読み取るソケット
  • に到着したアプリケーションに指示し、サーバーに到達します。
  • 読み取りを繰り返すと、EAGAIN/EWOULDBLOCKを返します。

この場合、読み取りは「アトミック」ではありません。データが単一の書き込み操作で書き込まれたとき、読み取りは全体を1つの部分に戻すことは保証されていません。

データが部分的なときを知ることはできますか? 1つの解決策は、常にデータサイズを最初に追加することです。あるいは、別の方法では接続をいつでも閉じて再オープンすることができますが、私はこれらをやりたいとは思いません。カーネルは、ブロッキング操作のアトミック性を保証するため、「パッケージ」(BTWと呼ばれるユニットはどのように到着しましたか)が到着しました。

多くの感謝!

+3

あなたは、一般的に*ループ*内のすべてのI/Oを書いて、あなた自身のバッファを維持する必要があります。 –

+0

ソケット上の 'read'呼び出しが' 0'を返さなかった場合、イベントループで取り込むことができるより多くのデータが存在することが期待できます。 – jacob

+0

バイナリ送信では、送信の開始や送信の終了などの区切り文字を追加するのが一般的です。テキスト送信では、構文チェックはあなたの友人です。 json文字列を送信する場合は、json文字列を解析して、完全かどうかを判断できます。 – alvits

答えて

1

TCPはストリームベースであり、メッセージ指向ではありません。ブロッキングソケットの場合であっても、アプリケーションが送信するものが一度にワイヤ上に移動することは保証できません。 TCPは独自のコースを決定します。

だから、「原子」の読書をするのはアプリケーションに任されています。たとえば、次のようになります。

アプリケーションプロトコルでは、メッセージの先頭にlengthバイトを付加する必要があります。長さバイトは、関心のあるアプリケーションデータのサイズをピアに通知する。もちろん、2バイト長のインジケータがいつ始まるかは、アプリケーションが認識している必要があります。

[2バイトMSG長] [関心のデータバイト]

この情報に基づいて読み取りを行うアプリケーションは、アクションを取る必要があります。msg lengthバイトで示されるすべてのバイトを受け取るまで、ソケットをポーリングする必要があります。その後、データを処理します。

"アトミック"読み取りが必要で部分読み取りでない場合は、recvにMSG_PEEKフラグを使用できます。ソケットバッファからデータを削除してはならない。アプリケーションはソケットに覗き見、戻り値に基づいて必要な数のデータがソケットバッファにあるかどうかを確認します。

ret = recv(sd, buf, MAX_CALL_DATA_SIZE, MSG_PEEK);

+0

私はそれを受け入れるだろうが、私はそれを受け入れることはできません;)あなたはこれを追加することもできますが、 "ブロッキングケースに関するあなたの推測は正しくありませんでした。 –

+0

NP!より多くの評判のために幸運。受け入れることを覚えておいてください;-) – Prabhu

+0

答えが役に立つなら、upvote/acceptに可能ですか? – Prabhu