0

ソケットプログラミングを使用してハードウェアボードと通信するためにサーバークライアントモデルを使用しています。

指定された最大サイズのバッファを読み取り、バッファ内の有効なデータの長さを返す「NetworkStream」クラスの「read()」メソッドを使用してボードからデータを受信します。十分な数のバッファの最大サイズを検討しました。

ボードは100msごとに一連のメッセージを送信します。各メッセージは、2バイトの定数ヘッダーと、ヘッダーバイトの後のデータとしての可変バイト数で構成されます。

問題は、メッセージが1つずつ受信されないことです。代わりに、バッファに2つまたは3つのメッセージが含まれているか、1つのメッセージが2つのバッファの間に散在している可能性があります。

現在、一定のヘッダーバイトを使用してメッセージのコンテンツを収集するDFAを使用しています(メッセージの長さはわかりません。ヘッダーバイトだけがわかります)が、問題は、データバイトにヘッダーバイトがランダムに含まれている可能性があることです。 !!

特定のストリームまたはクラスを使用して、バッファから各メッセージのバイトを収集する効率的な方法はありますか?どうすればこの問題を克服できますか?!

4

1 に答える 1

1

コンシューマDFAとソケットクライアントの間にバッファコンポーネントを追加する必要があります。

データがバッファから利用可能であるときはいつでもNetworkStream、バッファコンポーネントはそれを読み取り、それをそれ自身のプライベートバッファに追加し、「利用可能なバイト」カウンタをインクリメントします。バッファコンポーネントは、少なくとも次の機能をユーザーに公開する必要があります。

  1. プロパティ-これはBytesAvailableカウンターの値を返します
  2. PeekBytes(int count)メソッド-これは、少なくともその量が使用可能な場合、バッファーの最初のバイトを返し、countカウンターまたはバッファーを変更しません
  3. メソッド-上記と同じですが、ReadBytes(int count)カウンターをデクリメントしcount、バッファーから読み取られたバイトを削除して、後続のPeekBytes呼び出しがそれらを二度と読み取らないようにします。

count任意に高いパラメータを処理できる必要はないことに注意してください。count常に受信できる最長のメッセージを処理できれば十分です。

明らかに、バッファコンポーネントは、ある種の「ラップアラウンド」を可能にするある種のデータ構造を保持する必要があります。循環(リング)バッファの実装を調べるか、最長のメッセージの長さであるサイズの2つの固定バッファを使用して、いっぱいになったときに一方から他方に切り替えることができNますNNetworkStreamバッファがいっぱいになった場合にデータのプルを停止し、DFAがReadBytesバッファスペースを解放するために呼び出した後にのみプルを続行するように注意する必要があります。

DFAがデータを読み取る必要があるときはいつでも、最初にバッファステージに蓄積されたデータの量を尋ね、次にそれに応じて続行します。次のようになります。

if BytesAvailable < 2
    return; // no header to read, cannot do anything

// peek at the header -- do not remove it from the buffer!
header = PeekBytes(2);

// calculate the full message length based on the header
// if this is not possible from just the header, you might want to do this
// iteratively, or you might want to change the header so that it is possible
length = X; 

if BytesAvailable < X
    return; // no full message to read, cannot continue

header = ReadBytes(2); // to remove it from the buffer
message = ReadBytes(X); // remove the whole message as well

このようにして、DFAはメッセージ全体のみを処理します。

于 2012-09-22T23:10:04.507 に答える