サーバーが固定ウィンドウ サイズの単一ポートを介してクライアントにパケットを送信し、クライアントが受信した各パケットに対して ack パケットを返す UDP サーバー/クライアント プログラムを作成しています。ここで、サーバーがパケットの損失状況を処理するようにします。いくつかのグーグルでは、ALARM
またはを使用する必要があるようSELECT
です。確かに、1 つのパケットを送信して、ack またはタイムアウトを待ってから別のパケットを送信することはしたくありませんがSELECT
、タイムアウト中に呼び出し関数をブロックするので、良くないと思います。ALARM
1 つのプログラムは 1 つしか持つことができないため、どちらも良くありませんALARM
。サーバーが送信する複数のパケットのタイムアウトを追跡できるようにする方法はありますか?
2 に答える
真っ先に思いつくのは以下。
非ブロック モードでリッスンするソケットを開きます。ノンブロッキングが重要です。何かが存在することを select が示しているが、イベントが適切に配置されている場合、それは別の場所で処理される誤ったアラームである可能性があり、来ていない何かをブロックすることは問題です。
送信されたパケットごとに、タイムアウト時間の昇順で並べ替えられたリンクされたリストを保持します。
応答が受信されると、リンクされたリストから削除されます。
select を使用して、妥当なタイムアウトで次の着信パケットを待ちます。まれな「念のため」の状況をカバーするためにはより長いタイムアウトが合理的であるように見えても、私は最大数秒を使用する傾向があります. ここでブロックしているのは着信パケットですが、次のタイムアウト以降ではありません。
select が返されたら、リクエストが利用可能な場合は、accept() してリクエストを処理します。
ループ ハンドルを反復する前に、新しいタイムアウトを処理し、必要に応じてリンク リストを調整します。
Web をすばやく検索すると、 http://www.lowtek.com/sockets/select.htmlで詳細が見つかりました。
select() は、recvmsg() がブロックするのと同じ方法でブロックします。タイムアウト付きの代用です。SO_RCVTIMEO オプションを使用して読み取りタイムアウトを設定することもできます。これは、プラットフォームでサポートされている場合はより簡単です。