質問

クライアント側のカウンター変数があるとします。サーバーにリクエストを送信するときは、この変数の値を送信し、(サーバーへの次のリクエストのために) 1 ずつ値を増やします。サーバーはこのカウンタを独立して追跡し、クライアントによって送信されたカウントが自身の (サーバー側の) カウントのコピーよりも 1 多いかどうかを確認します。これはすべて問題なく素晴らしいことですが、次の状況を考えてみましょう。

  1. クライアントは、たとえば 23 をサーバーに送信します。
  2. サーバーは 23 を受信し、それを検証し、自身のカウンターを 23 にインクリメントします。
  3. サーバーはクライアントに All-OK コードを返します

-しかし-

サーバーからクライアントに送信される途中で、リターン コードが破損します。したがって、クライアントはサーバーがカウンターを更新しなかったと考え、クライアント側のカウンターを 23 のままにします。この時点から、クライアントとサーバーは同期されなくなります。

このような破損やエラーの可能性に直面しても機能する堅牢なスキームを知っている人はいますか?

ありがとう、
キャメロン

役に立ちましたか?

解決

線形に増加するカウンターを使用する代わりに、適切な 64 ビット以上のエントロピーのランダムな「ノンス」値を使用できます。サーバーがクライアントからリクエストを受信すると、サーバーは nonce がクライアントに最後に送信した nonce と一致するかどうかを確認します。そうである場合、リクエストは処理され、サーバーは応答で送信する新しいランダムな nonce 値を生成します。

サーバーは、最後の 2 つの nonce 値を保持してクライアントに送信できます。クライアントが古い値を送信した場合、サーバーはクライアントへの最新のメッセージが失われた可能性があると想定します。

上記の方法では、2 つの異なるクライアントが同じ資格情報を使用してサーバーと通信するのを防ぐことが目標であると想定しています。nonce メソッドを使用する利点は、次の値を簡単に予測できないことです。

他のヒント

簡単な答えは、クライアントまたはサーバーの両方に独自のリソースのコピーを作成するのではなく、どちらか一方をリソースの所有者にすることです。

ただし、TCP などの信頼できるプロトコルを使用している場合は、メッセージがクライアントに届かないことを心配する必要はありません。

ただし、クライアント/サーバーの作業を行うときに従うべきことは、すべての操作を冪等にすることです。つまり、各関数は副作用なしに 1 回または複数回呼び出すことができます。この場合、「インクリメント」関数はまったくありません。代わりに、「set」関数があります。

サーバーがサーバーカウンターの更新を確認するまで、クライアントがローカルコピーを更新しないようにするのはどうでしょうか。

それで:

クライアントの次の値の計算クライアントは、次の値が有効である(まだ見られていない)サーバーの更新が次の値にカウンター(必要に応じて)サーバーのサーバーチェックに次の値を送信します(必要に応じて)クライアントに次の値が受信されたことをクライアントに通知します。

サーバーがクライアントの更新を受信しない場合、クライアントは計算された次の値を再送信するだけです。クライアントが次の値の確認を受信しない場合、次の値を再送信しますが、すでにそれを認識しているサーバーは更新せず、単に確認応答するだけです。最終的に、クライアントはサーバーのメッセージを確認して続行します。これは、メッセージが失われた場合にも当てはまります。

破損が心配な場合は、メッセージのチェックサムを計算して送信してください。受信時にチェックサムを再計算し、送信されたチェックサムと比較します。ただし、通常はネットワーク スタックがこれを行うため、独自のプロトコルを実行している場合を除き、あまり心配する必要はありません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top