Node.jsでUDPを使用してメッセージの配信を保証するにはどうすればよいですか?たとえば、パケットが失敗した場合に再送信することもできますが、失敗したタイミングを特定する方法はありますか?また、パケットの損失はどのくらい一般的ですか?
4 に答える
あなたが本当に疑問に思っているのが「失われたパケットをどのように検出するか」である場合はどうすればよいですか?次に、一般的な手法は、送信されたパケットごとに受信者に確認応答を送信させることです。送信機が確認応答を受信しない場合は、パケットを再送信する必要があります。受信者が重複パケットを受け取った場合、重複を破棄する必要があります。
基本的なスキームは次のとおりです。
TX RX
╷ data
╰──────────────────────────────▶
ack ╷
◄──────────────────────────────╯
╷ data
╰────────────────────── - - - loss of data packet
.
.
. timeout
.
╷ data retransmit
╰──────────────────────────────▶
ack ╷
◄──────────────────────────────╯
╷ data
╰──────────────────────────────▶
ack ╷
- - - ────────────────────╯ loss of ack packet
.
. timeout
.
╷ data retransmit
╰──────────────────────────────▶
ack ╷
◄──────────────────────────────╯
これは基本的に、すべての形式のパケット損失検出の基礎です。技術を改善するために実装できるいくつかの改良点がありますが、基本は一般的に同じです。受信者がパケットが到着したことを通知しない場合、パケットは失われます。
アルゴリズムに対して一般的に行われる最初の改善の1つは、ackが本当に適切なackであり、ルーター、信号相互干渉、またはソフトウェアのバグによって送信されるエコーだけではないことを確認することです。解決策は、トグルビットを実装することです。データパケットはトグルビットを値に設定して送信され、ackパケットは適切な値(通常は同じ値)で応答する必要があります。トグルビットが間違っている場合は、ackパケットが最後のデータパケットと一致しないことを意味します。これは、前のデータパケットと一致することを意味します。これは、最後のデータパケットが確認されていないことを意味します。つまり、問題が深刻に発生しているため、正しいackが受信されるまでパケットを再送信する必要があります。
TX RX
╷ data[0]
╰──────────────────────────────▶
ack[0] ╷
◄──────────────────────────────╯
╷ data[1]
╰──────────────────────────────▶
ack[0] ╷
◄──────────────────────────────╯ ack mismatch!
╷ data[1] retransmit
╰──────────────────────────────▶
産業機器やロボットの制御に使用されるほとんどのプロトコルを含む、いくつかの実際のプロトコルがこの手法を使用しています。
次のステップは、実際には上記のアイデアの拡張です。少しだけ送信する代わりに、番号を送信してみませんか。これにより、ackをデータパケットとより確実に一致させることができるため、失われたパケットと再送信が必要なパケットをより正確に検出できます。この手法は、ある時点で数値がロールオーバーしてゼロに戻るため、スライディングウィンドウ手法と呼ばれることがよくあります。したがって、パケット損失を検出できなくなる前に送信できるパケットの最大数は、スライディングウィンドウサイズです。
スライディングウィンドウ手法の大きな利点は、ACKを待たずに大量のデータパケットを送信できることです。これにより、スループットが大幅に向上します。
TX RX
╷ data[1]
╰──────────────────────────────▶
╷ data[2]
╰──────────────────────────────▶
╷ data[3]
╰──────────────────────────────▶
ack[1] ╷
◄──────────────────────────────╯
ack[2] ╷
◄──────────────────────────────╯
╷ data[4]
╰──────────────────────────────▶
╷ data[5]
╰──────────────────────────────▶
ack[3] ╷
◄──────────────────────────────╯
ack[5] ╷
◄──────────────────────────────╯ ack[4] missing!
.
. timeout
.
╷ data[4] retransmit
╰──────────────────────────────▶
したがって、上記はパケット損失を検出するための基本的な手法の簡単な要約です。これは、すべてのUDPパケットを宛先に到着させる場合に実装する必要があるものです。
ただし、TCPはすでにこれを実装しているので、車輪の再発明をしたくない場合は、実際にTCPを使用する必要があります。UDPが作成されたのは、パケット損失が問題ない場合があるためです(オーディオ/ビデオストリーミングを考えてみてください)。
ウィキペディアから
UDPは、エラーチェックと訂正が不要であるか、アプリケーションで実行される目的に適しており、ネットワークインターフェイスレベルでのそのような処理のオーバーヘッドを回避します。時間に敏感なアプリケーションは、UDPを使用することがよくあります。これは、遅延パケットを待つよりもパケットをドロップする方が望ましいためです。これは、リアルタイムシステムではオプションではない場合があります。[2] ネットワークインターフェイスレベルでエラー訂正機能が必要な場合、アプリケーションは、この目的のために設計された伝送制御プロトコル(TCP)またはストリーム制御伝送プロトコル(SCTP)を使用できます。
基本的に、パケット/メッセージがそこに到達する場合は、気になる場合はTCPを使用します。それ以外の場合は、アプリケーションレベルでUDPを使用してTCPを再発明します。
node.jsだけでなく、どのプラットフォームでも特定のUDPパケットの配信を保証することはできません。探しているのがUDPベースの信頼できる配信メカニズムである場合は、e-netのようなものを探すか、信頼できるUDPを検索してください。
編集:またはTCPを使用します。
UDPは、配信が保証されていないプロトコルです。保証したい場合は、UDPの上にいくつかのプロトコルを実装する必要があります。