約 2,236,857 件
https://w.atwiki.jp/selflearn/pages/20.html
ここでは、pingコマンドのソースコードを調べ、まとめた内容を記録していきます。 開始日 2007年01月23日 最終更新日 2009年06月01日 はじめに 目標 pingソースを読むにあたって、それぞれ次のような目標で進めます。 kato「パケット送信~受信の流れを掴み、自分でもpingパケットの送受信ができるようになる。pingコマンドのオブションに詳しくなる」 ichi「コマンドオプションの取り扱いやパケット送受信の処理方法などの定石を知り身につける。各ファイルの意味・役割についてもしっかり理解する。C言語を思い出す:P」 使用ソースコード GNUソフトウェアinetutils-1.5を使用します。コンパイル・インストール方法はping(メモ)を参照してください。 TODO 進めていく中で、やること・やりたいことを書いてください。終わったら黒く塗りつぶすこと。必要に応じて細分化してもオッケーです。 ■ 指定可能なオプションの一覧作成 □ 各ファイルの用途をまとめる □ オプション未指定で起動したときの処理フローを調べる。関数コールの流れが分かると良い □ ping_echo.cの調査。他のソースはping_echo.cが終わってから □ パケット送信処理のルールを追う。ping_echo.cでのパケット生成~送信の流れをまとめる □ パケット受信処理のルールを追う。パケットの受信待ち~受信~情報取得~画面表示の流れをまとめる がんばりましょう。 外部インタフェース この章では外から見えるpingの振る舞いについて記述します。 そもそも、pingコマンドって何なの? ICMP ECHO_REQUESTパケットをネットワーク上のホストに送信するプログラムです。対象ホストが到達可能かどうかをテストします。 pingプログラムはICMPのECHO_REQUESTメッセージを送信し、ホストやゲートウェイから返信されるICMPのECHO_REPLYメッセージを受信します。ECHO_REQUESTメッセージはIPとICMPヘッダーを持っていて、送信した時刻(struct timeval)と指定したサイズぶんのパディングデータによって構成されています。(*1) 指定可能なオプション ※とりあえずping.8から抜粋。後でソースと比較し、きちんとまとめます。 オプション 処理(ロングオプション) -V --version バージョン情報を表示して終わる -L --license ライセンス情報を表示して終わる -h --help 使用方法を表示して終わる -c (count) --count ECHO_REQUESTの最大送信パケット数(またはECHO_REPLYを受信した数)で送信を止める -d --debug ソケットにSO_DEBUGオプションを付けて実行する -r --ignore-routing 通常の経路テーブルを無視(バイパス)し、接続されたネットワークのホストにダイレクトに送信する。もし対象ホストが接続されたネットワークに存在しない場合はエラーが返る。このオプションは(当該ホストへの)経路情報を持たないローカルホストに対して有効である。(e.g., after the interface was dropped by routed(8)). -s (size) --size ECHO_REQUESTパケットのサイズを指定する。デフォルトは56bytesで、これはICMPヘッダを含めるとちょうど64bytesになる。 -i (wait) --interval 各ECHO_REQUESTの送信間隔を秒で指定する。デフォルトは1秒。このオプションは-fと同時に設定することはできない。 -n --numeric IPアドレスを10進数表記により出力する。ホスト名をルックアップする処理は行わない。 -v --verbose 標準出力に対し情報を出来る限り出力する。ECHO_REPLY以外のICMPパケットも受信すれば出力する。 -t (type) --type ("echo"/"timestamp"/"address"/"router") ICMPのメッセージタイプを設定する。このオプションは次に示す3つのオプションのどれかを設定したときと同じ結果を生む - --echo ICMP echoメッセージを送信する(デフォルト動作) - --timestamp ICMP timestampメッセージを送信する - --address ICMP addressメッセージを送信する - --router ICMP router discoveryメッセージを送信する。現在は未対応 -f --flood 100回/秒かそれ以上のパケットを送信する、「pingの洪水(flood)」を発生させる。ECHO_REQUESTを送信するごとにピリオド「.」を1文字出力し、ECHO_REPLYが届くごとに削除する。したがって画面上に表示されたピリオドの数が破棄・消失したpingパケットの数として確認できる。このオプションはネットワークに対して強烈な負荷をかけるため、スーパーユーザーでのみ設定可能 -l (preload) --preload 通常のping送信処理に入る前に、preloadで指定した個数のECHO_REQUESTを出来るだけ早く送信する。preload={1,65535} -p (pattern) --pattern パディングする値を16進数で設定する。このオプションはデータが崩れる問題を抱えたネットワークで有効である。たとえば"-p ff"と設定した場合、ペイロード部のビットは1で埋められる。 -q --quiet 開始/終了時のサマリー以外情報を出力しないようにする。 -R --route pingパケットの通った経路を記録し表示する。ECHO_REQUESTにRECORD_ROUTEオプションをつけることで経路を記録していき、戻ってきたECHO_REPLYに含まれる情報を表示する。注意:IPヘッダに記録しておける最大経路数(9?)には注意すること。(残念ながら)多くのホスト・ルータではこのオプションを無視する。 出力情報の見方 送信中 # ping hoge_host PING hoge_host (192.168.0.3) 56 bytes of data. 64 bytes from 192.168.0.3 icmp_seq=1 ttl=64 time=0.114 ms 64 bytes from 192.168.0.3 icmp_seq=2 ttl=64 time=0.176 ms 64 bytes from 192.168.0.3 icmp_seq=3 ttl=64 time=0.170 ms まず、先頭の出力: PING hoge_host (192.168.0.3) 56 data bytes. は、「hoge_host(IPアドレスは192.168.0.3)に対しデータ長56バイトのECHO_REQUESTを送信する」という意味です。データ長はICMPヘッダとIPヘッダを除いたプリロード部のサイズを表します。 次の出力; 64 bytes from 192.168.0.3 icmp_seq=2 ttl=64 time=0.176 ms は、ECHO_REQUESTに対するECHO_REPLYパケットを受信する度に出力されていきます。 最初の「64bytes」は送信時と違いICMPヘッダ+データ部の合計を表示していることに注意してください。 「icmp_seq=X」はECHO_REQUESTに付けられたシーケンス番号であり、この値の連続性を見ることで、どのパケットが破棄されたかが分かります。 「ttl」はECHO_REPLYのttlフィールドの値を表します。この値はIPルーティングされるたびにデクリメントされるので、ECHO_REPLYが幾つルータを経由してきたかが分かります。言い換えると、ECHO_REQUESTがルータを経由した回数は分からないことを表しています。 「time」はECHO_REQUESTを送信してからECHO_REPLYを受信するまでに要した往復時間(Round Trip Time)を表示します。厳密には、 Start ECHO_REQUEST送信時にデータ部に付与しておいた時刻情報 End 情報を出力しようとしたときの現在時刻 を調べ、両者の差をRTTとして出力しています。なおWindowsのECHO_REQUESTパケットには時刻情報がセットされていないため、PC内部で時刻情報を管理・出力していると思われます。 一方、ECHO_REPLYがタイムアウト時間までに届かなかった場合は以下の情報が出力されます。 64 bytes from 192.168.0.1 Destination Host Unreachable(etc.) Vr HL TOS Len ID Flg off TTL Pro cks Src Dst Data 4 5 00 5400 0000 0 0040 40 01 9c02 192.168.0.1 192.168.0.60 エラーの理由と、送信したIPパケットの情報を出力します。 この後Ctrl+c(SIGINTシグナル)を入力するか、または-cで指定した個数のpingを送信完了すると以下のサマリー情報を出力して終了します。 --- hoge_host ping statistics --- 10 packets transmitted, 10 packets received, 0% packet loss round-trip min/avg/max/stddev = 0.120/0.259/0.659/0.231 ms # 上記は 「10パケットを送信したうち10パケット受信し、破棄率は0%。RTTの最小/平均/最大/標準偏差はそれぞれ0.120/0.259/0.659/0.231msだった」 ことを表しています。これまで送信したパケットについての統計情報です。 ファイル構成 各ファイルの概要 pingフォルダ内のMakefile.am(automakeで使用するMakefileの種、みたいなもの)から抽出。ファイルはまだ他にもあるっぽいので、随時追加。 ファイル名 概要 ping.c ping_echo.c ping_address.c ping_router.c ping_timestamp.c ping_impl.h ping構成ソース全般でインクルードするヘッダファイル。マクロ(用途不明)と時間の統計情報を計算するための構造体が定義されている。 各ファイルのつながり 「ping IPアドレス -c 10」と実行した時の、pingの各ファイル間の構成は次のとおりです。エントリポイントはping.cです。 図の太い線は、Pingが送受信されるごとに関数がコールされているものを表しています。細い線は1回の実行において1回しか呼ばれません。 処理の流れ 基本的な処理の流れ(IPアドレスだけ指定したとき) 関数がどのようにコールされていくかを簡単な説明付きで記述してください。オプション解析→ping開始準備→送信→受信→情報出力という流れを関数コールと紐付けられればベターです。 関数のコールグラフ 「ping localhost -c 4」と実行したときの、関数のコールグラフはこれです。 このコールグラフはpvtraceで作成したトレース情報をgraphvizでグラフ化しています。 グラフ作成の元になったdotファイルは、ここからダウンロードできます。 モジュール構成図 コールグラフを元に、機能面で抽象化したときのモジュール構成図は以下のとおりです。 モジュール構成を図示してください パケット送信 pingプログラムがパケットを送信する時、どのように送信しているかをまとめます。 ソケットの操作 パケットフィールドへのセット パケット受信 pingプログラムがパケットを受信するとき、どのようにしているかをまとめます。 ソケットの操作 パケットフィールドからの情報取得 各関数の処理詳細 各関数の詳細は、長くなるので別ページping(内部関数説明)に記載してあります。 ただしこの章の優先度は低いです。調べていく中で余裕があるときに書いてください。 使用しているテクニック・パターン モジュール構成、デザインパターンや処理内容など、特筆すべき内容をここに書きます。 関数ポインタによるポリモーフィズム pingコマンドで送信するICMPメッセージが異なると、ヘッダ情報、ペイロード、格納データなどがそれぞれで異なります。この処理を1処理の中でswitch文などにより場合分けをしてもよいのですが、pingでは関数ポインタによって処理を分割・抽象化しています。 ping.cのmain()関数でオプションを解析している中で、オプションによってはdecode_type()関数をコールします。この関数では、引数で渡された文字列を見て次のようにping_type変数に関数ポインタを代入しています。 if (strcasecmp (optarg, "echo") == 0) ping_type = ping_echo; else if (strcasecmp (optarg, "timestamp") == 0) ping_type = ping_timestamp; else if (strcasecmp (optarg, "address") == 0) ping_type = ping_address; #if 0 else if (strcasecmp (optarg, "router") == 0) ping_type = ping_router; #endif 各関数と送信するICMPメッセージの種類は以下のとおりです。 メッセージ 使用関数 ICMP echoメッセージ ping_echo() ICMP timestampメッセージ ping_timestamp() ICMP addressメッセージ ping_address() ICMP router discoveryメッセージ(未対応) ping_router() ping_type変数はping.c内でグローバル変数として定義されています(グローバル変数なのはmain()とdecode_type()の2箇所で利用されるからなのですが、その程度ならmain()のローカル変数で済むようにしたほうがスマートな気がします)。 int (*ping_type) (int argc, char **argv) = ping_echo; int型のargc,char**型のargvの2引数を持つ関数へのポインタ(初期値はping_echo)、という意味です。 そして、main()ではオプションの解析が終了したあと最後に return (*ping_type)(argc, argv); とping_typeに格納された関数をコールして終わっています。ICMPメッセージの種別でコールする関数を分けたりしていません。 利点は、呼ばれた側では自分自身が行うべき処理のみを記述すれば良いためメンテナンス性や(関係ない他処理による)バグの混入を防げることです。もしこれを関数ポインタを使わないとしたら、冒頭に挙げた「ヘッダ情報、ペイロード、格納データ」それぞれについて場合分けをして設定処理を記述しなければいけませんので。 また、呼ぶ側の処理内容を統一できている点も利点の1つです。将来の処理追加に対して容易に対応できることが分かると思います。 static関数を別ファイルの関数からコールする static関数であったとしても、別ファイルの関数からコールすることが出来ます。 関数のコールグラフを見ると、ping_echo.cの関数echo_finish()はping.cの関数ping_run()からコールされています。しかし、echo_finish()の関数定義を見ると、 static int echo_finish (void); というようにstatic宣言されています。staticを関数に適用した場合、宣言されたファイルの外側からは見えなくなるのですが、なぜか別ファイルからコールできています。 これは、ping_run()に対してecho_finish()の関数ポインタを渡しているためです。 ping_echo (int argc, char **argv) { return ping_run (ping, echo_finish); } int ping_run (PING *ping, int (*finish)()) { if (finish) return (*finish)(); ping_echo()からping_run()呼ぶときに、echo_finishのアドレスが渡されています。これによりping_run()でもecho_finish()を呼ぶときはどのアドレスにジャンプすればよいかが分かるようになります(もちろん、ping_run()からecho_finish()を明示的にコールすることは出来ません)。 このように、関数ポインタを渡すことでstatic関数でも外部ソースファイルから参照・コールすることができます。関数を公開する範囲を限定することができる点が利点です。 後述するコールバック関数による疎結合の実現でも重要なテクニックです。 クロージャによる関数とデータの一括 まずここでのクロージャは、「関数コールに常に伴うデータ構造(状態保持可)」という意味で考えてください。クロージャ作成による外部データの束縛、というような意味ではないです。 ping_echo.cの関数ping_echo()で、次のように関数を呼んでいます。 ping_set_event_handler (ping, handler, ping_stat); この最後の引数ping_statが、libping.cでは(void*)closureとして扱われ、この後の処理には必ず付いて回るようになっています。つまり、データ構造が処理に束縛されているのと同じ状況になっているのです。 そして呼ばれる先々でデータ構造は更新されていき、分散や平均を求めるのに役立っているわけです。 コールバック関数による管理部と処理の分離 pingのソースは、 pingでのプロトコル動作を実現 → ping.c pingパケットの情報を表示 → ping_echo.c pingパケットのヘッダ部作成や実際の送受信 → libping.c というように、処理によってファイルが明確に分かれています。1はパケットを受信したときに何をするか(ここでは情報の表示)をするのみになっていて、スタート時にはこれら処理の関数ポインタをping.cからping_echo.cに登録し、その次はping_echo.cからlibping.cに処理を登録しています。 関数を直接呼ばず、下位層にイベントハンドルとして登録することで、上位層に変更があっても下位層には影響を受けない、という関係になります。依存方向が片方向に限定されるわけです。 粗結合なので、オプション次第で別のping_address.cやping_router.cに特定層を切り替えても問題はないわけです。 構造化プログラミングやオブジェクト指向プログラミングでも、こうした考えは重要ですので、ぜひマスターしたい知識です。 気づいた・面白い・分からない点 コードを読んでいく中で、気付いた点を以下に記します。 kato (2007/1/23)コマンド追加時にもできるだけ既存処理の修正が少なくなるように設計されているなあ。関数ポインタによる抽象化、コールバック関数によるイベントドリブン(もどき)、などなど。クロージャもある!いやいや、思っていたよりも構造化されていて、参考になるよコレ。思っていたよりも難しい、とも言えるわけだけど。 (2007/2/7)main()でコマンドオプションを解析するときに、struct option long_options[]に対して長いオプションのvalメンバを1文字のオプション文字で設定している。そうか、こうすることで長いオプションと(同じ機能を持つ)短いオプションとを同じcase文の中で扱えるのか。細かいけれど、面白いテクニックだ。 (2007/8/2)このプログラムでは、自動変数をヒープ変数のように使っていることに気がついた。ある関数から次の関数への自動変数の受け渡しがreturn文中での関数呼び出しと共に行われているせいで(末尾再帰チック)、読んだ先の処理が終わるまではスコープの中のままになり、逆にスコープを意識しないでも良いような状況になっている。しかも自動変数なので処理が終われば解放をしてくれて・・・。テクニックの1つだけど、これも面白い。クラスやクロージャ、RAIIなどを言語そのものが提供していなくても、同じ機能を実装するテクニックは、機能を理解する上では大事なことだな、と思ったり。 ichi 気づいた点を書いてください。箇条書きにこだわる必要はないです コメント ※他の人が書いた文章はいきなり修正せず、コメントやメールで一度連絡を取り合ってからにしましょう。あくまで仲良く。 pingはBIOS画面の時点でレスポンスって返ってくるものなのでしょうか?初歩的な質問となってしまうのですが宜しくお願いします。 -- アナスタシア (2007-07-27 08 37 25) 普通は返ってこないと思います。pingはカーネルの上で動く1つのサービスであって、ネットワークスタックが、もしくは少なくともEthernetデバイスドライバは動いていないといけません。しかしBIOSの段階ではとても基本的なことしかできず(http //community.osdev.info/?(AT)BIOS参照)、Ethernetデバイスが動いて、IPが動いて、というのは非現実的、というか無理だと思います。なので、BIOSでPingが返ってくるようなものは無いと思います。(「思います」口調なのは、WakeOnLANとかはどうなっているの?と言われるとよく分かってなくて・・・すみません)ちなみに逆に質問なのですが、どうしてそのような質問をされたんですか?面白い(興味深い)質問でしたので、ぜひ聞かせてください。 -- kato (2007-07-29 23 55 27) ( - )
https://w.atwiki.jp/pmyy/pages/45.html
PINGの話 PINGは低ければ低いほど良いです。あまりにも高いとラグが発生します。 10~40くらいまでは体感できないレベルだと思います。 PING改善策 ①無線LAN → 有線にする。 ②不要なアプリケーションをアンインストールする。 注)以下の方法はパソコンに詳しい人向けです(PINGが劇的に改善したという報告もありません僕もわかりません) ③QoSパケットスケジューラのチェックをはずす。 ④オフロードを無効にする ⑤SNP(Scalable Networking Pack)を無効にする ⑥RWIN値最適化 ⑥MTU値最適化 ⑦TCPグローバルパラメーター設定 PINGとは 「サーバーとの応答速度」です。 ネットサーフィンが早くてもPINGが高い可能性もあります。 PINGはサーバーとの距離にも影響を受けますし、自分のネット回線の内容(回線の種類、プロバイダ、ルーターなどなど)にも影響を受けます。 通信速度測定をして通信速度が低ければ、回線の契約を見直すことで改善が期待できます。(bpsとPINGは別物です。) 通信速度は高いけど・・・PINGが高い・・・・という人はサーバーの場所を調べて引っ越ししたらもしかしたら早くなるかもしれないですね。にっこり ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Reference 1.http //intint000.blog96.fc2.com/blog-entry-444.html 2.http //latesanman.blog.fc2.com/blog-entry-45.html 合計: - 今日: - 昨日: -
https://w.atwiki.jp/ityo-go/pages/13.html
Ping 意味 ICMPを用いて任意の機器との疎通を確認 通信相手との往復にかかる時間を計測 ネットワークのMTU計測(ping -f -l 1472) 用法 最近○○ちゃんから、Pingの応答ないんだよね(´・ω・`)(メール送ったのにレスがない場合) ○○ちゃんにPing打ったんだけど、遅延がデカい(メール送ってから返信来るまでの間隔が長い) 備考 Pingの応答がない場合、エンドエンドではなく中間にある機器も被疑箇所である。中間機器を特定するにはTracerouteを行う パケットのドロップ、ロス、廃棄が発生しているかも(ファイアウォールなど) Pingを打つには相手のIPアドレスが必要(電話番号/メールアドレスなど) そのIPに到達するためのルーティングも必要(通信経路) IPアドレスを得るには、その前にMACアドレスが必要(別セグメントの場合はデフォゲのMAC)(名前とか?) MACアドレスがわからない場合は、ブロードキャストが必要(合コンに参加など) ブロードキャストを送るためにはLinkUpしていなければならない(とりあえずアクティブにならなきゃ!) 関連項目 Traceroute IPアドレス コメント
https://w.atwiki.jp/aster-infra/pages/45.html
指定されたホスト名またはIPアドレスに ICMPパケットを送り、その反応を表示する。 しかし宛先からの反応がなかった場合、 ホスト自身に問題があるのか、ホストに到達するまでの ネットワーク経路に問題があるのかわからない # ping ホスト名またはIPアドレス名 Ctrl + C キーを押して強制終了しない限り、パケットを送り続ける # ping -n ホスト名またはIPアドレス名 ホスト名を解決せずIPアドレスで表示する # ping -c 回数 ホスト名またはIPアドレス名 指定した回数だけパケットを送信する # ping -i 秒数 ホスト名またはIPアドレス名 指定した秒数ごとにパケットを送信する デフォルトは1秒になっている
https://w.atwiki.jp/wiki3_nab/pages/37.html
めも MTUの最適値確認方法 ping -D -s パケットサイズ 宛先アドレス ※rootで実行する
https://w.atwiki.jp/kakis/pages/7769.html
ping /// / 梅 \ lakti pindinバラ+gek丸 \
https://w.atwiki.jp/developmenttips/pages/68.html
ICMPは、パケットの配送中に障害が起こった場合のエラー通知や、 ネットワークの診断に利用されます。 pingコマンドでは、ICMPエコーメッセージを利用して通信の確認をしています。
https://w.atwiki.jp/honyakublogbuilder/pages/23.html
■PING送信 翻訳ブログビルダーのPING送信機能についてご説明します。 「ping送信」をクリックすると、PING送信画面が表示されます。 ブログリストでPING送信対象のブログを選択し、「開始」をクリックすると、 PING送信が開始されます。 PING送信先のサーバーは、デフォルトでかなりの数が登録されていますが、 自分で登録することも可能です。
https://w.atwiki.jp/i5031higashi/pages/4.html
Packet INternet Groper 指定のIPアドレスが存在するかどうかを確認するのによく用いられる。 ソナーが発する音波を「ping」(ピン)と称することから、これに掛けた言葉であるとの説がある。日本では、コンピュータ用語として用いる場合は「ピング」と発音するのが一般的。
https://w.atwiki.jp/freetool/pages/43.html
PING送信サービス PING送信プラス PING送信プラスを使用すると、各PINGサーバーへ指定したブログの更新情報が登録されます。各PINGサーバーへ登録されると、ブログ検索サイトの検索対象になるため、アクセス数の増加が見込めます!また、ウェブ検索にも登録されやすくなるため、SEO対策にも効果的です! 一括PING送信サイト ブログ(Blog)の更新通知情報を配信するPING送信機能をブラウザから簡単に行うことができるオンラインサイトを紹介。ユーザー登録などいっさい不要の無料サービスに限定してます。Yahoo! JAPANやGoogleは、このPING送信を受け付けており、その結果はブログ検索へと反映されます。 Yahoo!へのPING送信 http //api.my.yahoo.co.jp/rss/ping?u=あなたのサイトのRSSファイルのアドレス