recvt

Section: WIN SYSTEM (1W)
Updated: 2020.2.25
Index Return to Main Contents
 

呼称

recvt, recvtd - IPによる win 形式データの受信  

形式


recvt [-AaBDenMNr] [-d pkts] [-f chfile] [-g group] [-i interface] [-l min_psize] [-m before] [-o src_host:src_port] [-p after] [-s bufsiz] [-y req_delay] port shmkey shmsize [ ctlfile [ logfile ]]

recvtd [-AaBenMNr] [-d pkts] [-f chfile] [-g group] [-i interface] [-l min_psize] [-m before] [-o src_host:src_port] [-p after] [-s bufsiz] [-y req_delay] port shmkey shmsize [ ctlfile [ logfile ]]

 

解説

recvt は、自ホストの UDP ポート番号  port に宛てて送られる win 形式の データを受信し、キー  shmkey で与えられる共有メモリ・セグメントに(巡回的に)書き込みます。 そのキーをもつ共有メモリ・セグメントが存在しない場合は、大きさ  shmsize  (KB) の共有メモリ・セグメントが作られます。すでに存在している場合は、 そのサイズが  shmsize  (KB) よりも小さいとエラーになります。 UDP ポート番号は16ビットの整数値、共有メモリ・キーは32ビットの 整数値です。

recvtd は daemon モードで起動します。recvt でオプション -D を指定した時と同じ動作です。

制御ファイル  ctlfile が与えられた場合は、その中にリストされたチャネルのデータだけが 受信されます。ただし制御ファイル名の先頭に '-' を付けたときは、 そのファイルにリストされた以外の全チャネルのデータが受信されます。 制御ファイル名の先頭に '-' を付ける効果はチャネル番号による制御の 意味のみを逆転するもので、後述するホスト制御には影響しません。 ctlfile が与えられないか、または '-' である場合は、全チャネルが受信されます。
制御ファイル  ctlfile には、 1行に1チャネルずつ指定された16進数のチャネル番号(ただし"*"は 「すべてのチャネル」を表す)、または "+"か"-"で始まるホスト制御行を書くことができます。 チャネル番号を指定した行とホスト制御行は、混在していてもかまいません。 いずれの行も空白またはタブで区切られた左端の項目だけが読まれ、 その行の以降の部分は読み飛ばされます。'#'で始まる行はコメントと 見なされます。
ホスト制御行は、


       -host[:port]   パケットがhost[:port]からであれば捨てる
       +host[:port]   パケットがhost[:port]からであれば受け入れる
       +              パケットを受け入れる
       -              パケットを捨てる

の形式で書かれたルールです。ホスト名のあとに:で区切ってポート番号を 書いた場合は、ホストとポートの組が一致した場合にのみ有効になります。 ホスト制御については、パケットごとにルールを上から当てはめていき、 当てはまるルールがあったらそれが適用されます。最後まで当てはまるルールが なかったらそのパケットを受け入れます(つまり最後にはかならず "+" の行が あるのと同じ)。
 ctlfile にホスト制御行がない場合は、チャネル番号による選択のみが 行われます。1つ以上のホスト制御行がある場合、すべての ホスト制御ルールを適用した結果受け入れられたパケットに対して、 チャネル番号での選択が行われます。 したがって、  ctlfile にホスト制御行があってもチャネル番号を指定する行がない場合、 (制御ファイル名の先頭に '-'がない限り)すべてのデータが 捨てられてしまうことに注意してください。

ログファイル名  logfile を指定すると、ここに動作ログがとられます。指定しないとログ情報は標準出力に 送られます(ただし、daemon モードで動いている時は syslogd(8) に送られま す)。ログファイルは書き込みのたび毎にオープン/クローズされます。

recvt は、HUPシグナルを受けると制御ファイル  ctlfile と後述の  chfile を読み直し、ログファイル  logfile に送り元ホストごとの流量情報を書き出します。これには起動時、または 前回HUPシグナルを受けたときからの、

  パケット数、バイト数、毎秒パケット数、毎秒バイト数
が含まれます。ただしこの期間に1パケットも受信してない送り元 ホストについての情報は書き出しません。

recvt は受信するデータのチャネル番号ごとに過去10パケットまでの タイムスタンプの履歴を保存しており、同じチャネル番号で10パケット 以内に同じタイムスタンプのデータ(この場合1チャネル×1秒分の ブロックのことです)が来ると、重複しているものとしてそのデータを廃棄します。 この機能は、設定のミスによって無限ループができてデータが増殖する ことを防ぐことや、複数の送信元から1つの受信ポートへわざと重複した データを送信しておく冗長構成を可能にします。

recvt が受信するデータは、一般に記録の時間順に送られてくるとは 限りません。この場合、recvt が書き込んだ共有メモリ上でも、データは 時間順にはなりません。order(1W) はこれを時間順に並べ変えます。

recvt は引数なしで起動すると簡単な使用法を表示します。  

ネットワーク上の形式

データはネットワーク上を UDP/IP パケットで伝送されます。UDP パケットで 送られる内容は、

    (1)1バイトのパケット番号(0〜255)
    (2)1バイトの「元の」パケット番号(0〜255)
    (3)1バイトの識別コード(16進数で) "A0"
    (4)2バイトのブロックサイズ((4)〜(6)部分の合計バイト数)
    (5)6バイトの時刻ヘッダー(年〜秒、各1バイト、BCD形式)
         年の下2桁(00〜99)、月(01〜12)、日(01〜31)、
         時(00〜23)、分(00〜59)、秒(00〜59)
    (6)同一秒の1チャネル分以上のデータ(win形式)
    以降(4)〜(6)の繰り返し

で、これは通常 send_raw(1W)ファミリ(send_raw, sendt_raw, send_mon, sendt_mon)が送信したり、それをrelay(1W)が中継して来るものです。 (1)は送信元ポートが 各パケットにつける、1ずつ増える番号です(255の次は0に戻ります)。 (2)には通常(1)と等しい値が入っていますが、再送パケットの場合には、 (2)には再送要求された元のパケットの番号が入っていて、それが 再送パケットであることを示します。 1パケットのサイズは1472バイト以内(IPパケットサイズで1500バイト 以内)で、伝送効率のため、通常は なるべく大きくなるように上記(4)〜(6)の部分を次々に追加して 生成されます。なお、recvt は互換性のために、1パケットに1秒分しか 収容しない旧型のパケット形式

    (1)1バイトのパケット番号(0〜255)
    (2)1バイトの「元の」パケット番号(0〜255)
    (3)6バイトの時刻ヘッダー(年〜秒、各1バイト、BCD形式)
         年の下2桁(00〜99)、月(01〜12)、日(01〜31)、
         時(00〜23)、分(00〜59)、秒(00〜59)
    (4)1チャネル分以上のデータ(win形式)

も受け入れることができます。  

再送プロトコル

送信側は発生したデータを上記の形式で UDP パケットに入れて 送り出し、基本的に流量制御は行ないません。受信側は送信元 (ホストとポートの組)ごとにパケット番号を 監視していて、欠落したパケットの番号を送信元ポートに送ることによって、 そのパケットの再送を要求します。再送要求パケットは、再送して欲しい パケット番号だけを内容とする、データ部分の長さ1バイトの UDP パケットです。 送信元は再送要求されたパケットを 送り直します。通常の実装では、送信プロセスは過去最大128パケット まで遡った再送に応え、受信プロセスは最大64パケットの連続した 欠落までを再送要求します。recvt はパケット番号の連続性を監視して 再送要求を行なう相手先として、100ヶ所までの送信元を認識することが できます。100ヶ所を超えると、recvt は送信元テーブルを一旦白紙に戻し、 改めて登録を始めます。  

共有メモリ上の形式

recvt が共有メモリに書き込むデータは、1秒分ずつのブロック形式です。 1ブロックの構造は次のようになっています (オプション -B による別のもう一つの形式については オプションの項を見てください)。

    (1)4バイトのブロックサイズ(バイト)
    (2)4バイトの「書き込み時刻」
    (3)6バイトの時刻ヘッダー(年〜秒、各1バイト、BCD形式)
         年の下2桁(00〜99)、月(01〜12)、日(01〜31)、
         時(00〜23)、分(00〜59)、秒(00〜59)
    (4)同時刻の1チャネル分以上のデータ(win形式)

(2)は1970年1月1日0時から数えた秒数で示され、order(1W) が データを時間順に整列させるときに、タイムアウトを設定するのに 利用されます。共有メモリ ・セグメント全体は、次のような構造体になっています。

   struct Shm {
     unsigned long p;         /* write point */
     unsigned long pl;        /* write limit */
     unsigned long r;         /* latest */
     unsigned long c;         /* counter */
     unsigned char d[SIZE];   /* data buffer */
     } *sh;

p, pl, r, c は管理用の変数、d がデータの領域で、これらはすべて 1つの書き込み側プロセスによって書き込まれます。読み出し側プロセスは これらの変数を使って同期をとって、データを読み出します。
p
現在書き込み中のブロックの先頭位置(d の先頭からのバイト数)。
pl
ここを越えては新しい秒ブロックに入らず、先頭に戻る位置(d の先頭から のバイト数)。これは共有メモリセグメントの大きさの90%の位置に とられます。最後の秒ブロックはこの位置を越えて書き込まれますが、 そのブロックは、共有メモリセグメントの終端までには終わらなければ なりません。したがって、共有メモリセグメントの大きさは、少なくとも、 最大の1秒ブロックの大きさの10倍以上である必要があります。 ただし、残存メモリのサイズが10MBを越える場合(共有メモリの大きさを100MB より大きく取った場合)、メモリの有効活用のため残存メモリサイズが10MBに なる位置に設定されます。
r
最後に書き込み完了したブロックの先頭位置(d の先頭から のバイト数)。
c
これまでに書き込んだブロック数の積算値。

recvt は、連続して受け取ったデータパケットの 時刻が同じである限り、共有メモリ上の1つのデータブロックを 拡張していきます。従って受信したパケットと共有メモリ上のデータ ブロックは必ずしも1対1には対応せず、同じ時刻の複数のパケットは、 1つのデータブロックにまとめられます。  

オプション

-A
タイムスタンプをチェックしません。タイムスタンプのない 形式のパケットも扱うことができます。受信した1パケットが 必ず共有メモリ上の1ブロックになります。
-a
"A1"以上の種別コードをもつパケットも受け入れます。"A1"以上の 種別コードのパケットの場合は、種別コードもそのまま共有メモリに コピーされ、共有メモリ上の形式は recvs(1W) に説明されるものに なります。このとき、タイムスタンプまではチェックされますが、 それ以降のデータ部分のチェックされず、そのまま共有メモリに コピーされます。チャネルによる選択は行なわれません。また、 同一タイムスタンプをもつ複数のパケットが1つにまとめられることはなく、 受信された1つのパケットは、共有メモリ上でも必ずタイムスタンプ付き の1つのブロックになります。"A1"以上の種別コードをもつパケットを 受信するはずのない場合は、不正な(壊れた)パケットを判別しやすく するために、このオプションをつけない方が安全です。
-B
共有メモリに次のような別の形式(ブロック末尾にもブロックサイズを 持つ形式)で書き込みます。

    (1)4バイトのブロックサイズ(バイト)
    (2)4バイトの「書き込み時刻」
    (3)6バイトの時刻ヘッダー(年〜秒、各1バイト、BCD形式)
         年の下2桁(00〜99)、月(01〜12)、日(01〜31)、
         時(00〜23)、分(00〜59)、秒(00〜59)
    (4)同時刻の1チャネル分以上のデータ(win形式)
    (5)4バイトのブロックサイズ(バイト)

これはデフォールトの形式と(5)の部分だけが異なります。(1)と(5)には 同じ値が入っており、これは(1)〜(5)をすべて含んだ1ブロックの サイズです。この形式は、後方から(アドレスの高い方から低い方へ) のサーチを可能にするためのものです。この形式では、共有メモリ構造体の 中の変数 pl は、共有メモリ先頭に戻る直前に書き込まれた最後の ブロックの(5)の位置を示します。読み出し側プロセスは、pl を 「ここを越えては新しい秒ブロックに入らず先頭に戻る位置」として 使用することができるとともに、後方サーチの起点(先頭から折り返して戻る点) として利用することができます。読み出し側プログラムでは、共有メモリが この形式であるかどうかを自動判別するのが普通です。 この形式は、order(1W) の絶対時刻準拠モードに利用されています。
-D
daemon モードで起動します。
-d pkts
recvt はチャネル番号とタイムスタンプの履歴を持っていて、受信した データ(1チャネル×1秒分のデータブロック)のチャネル番号とタイムスタンプを 検査し、すでに受信されていると読み捨てます。この履歴の長さを pkts パケット分にします。デフォルトは10パケット分です。
-e
受信パケットを捨てるべき送り元ホストからのパケットを受信したら ctlfilechfile を読み直します。
-f chfile
ファイル chfile に指定されたチャネルを受信します。これは ctlfile での設定を補足するものです。まず ctlfile にしたがって受信すべきチャネルが決定され、 さらに chfile に指定されたチャネルが、受信すべきチャネルのリストに 追加されます。 chfile では、いずれの行も空白またはタブで区切られた左端の項目だけが読まれ、 その行の以降の部分は読み飛ばされます。'#'で始まる行はコメントと 見なされます。 ctlfile と違って chfile にはホスト制御やワイルドカードによるチャネルの指定は できません。 このオプションは複数個指定することができ、それにより複数(最大30個)の チャネルファイルを使用することができます。 recvt プロセスが HUPシグナルを受けたとき、 ctlfile とともに chfile も読み直されます。
-g group
IPマルチキャストアドレス group に対して送信されるパケットを受信します。
-i interface
データパケットを受信するネットワークインターフェースを、そのインターフェースの IPアドレス interface で指定します。再送要求パケットの送信元もこのIPアドレスになります。
-l min_psize
ペイロード部分のサイズが min_psize バイト未満の小さいパケットは不正パケットとみなして無視します。 デフォールトは16バイトです。
-m before
マシンの内部時計の時刻よりも before分以上前の(遅れた)タイムスタンプを もつパケットを、不正なパケットとして廃棄します。
-M
MON形式のデータを受信します。受信するデータがMON形式のときは これを指定しなければなりません。MON形式については raw_mon(1W)を 参照してください。
-N
パケット番号がないものとして扱います。したがって共有メモリ には受信したデータがまるまる(通常パケット番号が入っているはずの 先頭2バイトも含めて)書き込まれます。再送制御は行いません。 受信した1パケットが必ず共有メモリ上の1ブロックになります。
-n
拒否すべき送り元アドレスからのパケット、重複して受信した再送パケット、 不正なチャネルヘッダーをもつパケット、不正(許容時間範囲外を含む)な タイムスタンプをもつパケット、サイズが小さ過ぎるパケットについての 情報をログに報告しません。
-o src_host:src_port
ホスト src_host のUDPポート src_port へ1秒に1回、(複数のパケットに分かれている場合はその数だけ) 送信要求パケットを送ります。 送信要求パケットには受信したいチャネル番号のリストが含まれています。 送信要求パケットはデータ部分の長さが8〜1032バイトで、 データ部分の長さが常に1バイトである再送要求パケットとは区別されます。 送信要求パケットの形式は次の通りで、バイト順はビッグエンディアンです。

    (1)4バイトの文字列 "REQ\0"
    (2)2バイトのパケット番号(値は0〜)
    (3)2バイトのパケット数(値は0〜)
    (4)チャネル数×2バイトのチャネル番号のリスト(最大512個)

すべてのチャネルを要求する場合は、(2)と(3)がいずれもゼロで、 (4)はありません。要求するチャネル数が512以下の場合は、 (2)と(3)がいずれも1で、(4)にチャネル番号が羅列されます (特にチャネル数がゼロの場合は(4)がありません)。 要求するチャネル数が512を超える場合は、複数(ここでN個とします)の パケットに分割して送られます。その場合、(3)にはNが入り、(2)には N個中何番目のパケットであるか(1〜N)が入ります。 送信要求パケットは、通常 -f オプション付きの send_raw(1W) ファミリ により受信され解釈されます。送信要求の宛先は、正確に データパケットの送信元ホスト/ポートでなければ送信元に対する効果は なく、そのためには一般的には送信元の send_raw(1W) ファミリは -p オプションで送信元ポートを指定されている必要があることに 注意してください。
-p after
マシンの内部時計の時刻よりも after分以上後の(進んだ)タイムスタンプを もつパケットを、不正なパケットとして廃棄します。
-r
再送要求パケットを送信しません。 DVB衛星配信ボードによる受信のような一方通行の伝送路の場合には、 これにより不要なパケット送信を抑制することができます。
-s bufsiz
受信ソケットバッファサイズを bufsiz KBにします。ただしこれはシステムで許される値の範囲でなければ なりません。デフォルトは256KBです。再送要求が発生するとき、 netstat -s で表示される 「UDP: XXXX dropped due to full socket buffers」 などの値が増加していくなら、 bufsiz を増やすと効果があるかもしれません。
-y req_delay
再送要求するタイミングを req_delay パケット分だけ遅らせます。これにより、伝送中にパケット順が 入れ替わってパケット番号が不連続になっても、 req_delay パケットだけ待つことによって追い越されたパケットが到着すれば、 それに対する再送要求を出さなくてもすむことがあります。 最大60までの値が指定できます。
 

制御ファイルの設定例

次の2通りの場合は、いずれもホスト goodhost からのすべてのチャネルを受け入れ、 それ以外のホストからのデータは捨てます。

(1) recvt 7000 11 1000 ctlfile

   で、ctlfile の内容が

      +goodhost
      -
      *

   である場合。

(2) recvt 7000 11 1000 -ctlfile

   で、ctlfile の内容が

      +goodhost
      -

   である場合。
 

ソース

`recvt.c'
 

関連事項

winformat(1W), send_raw(1W), sendt_raw(1W), send_mon(1W), sendt_mon(1W), relay(1W), raw_mon(1W)


 

Index

呼称
形式
解説
ネットワーク上の形式
再送プロトコル
共有メモリ上の形式
オプション
制御ファイルの設定例
ソース
関連事項