3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

  • 意外とpingについて深堀する記事が少ないので書いてみました
  • 以前投稿したiperfの記事がそこそこ読んでもらえたので測定シリーズみたいな感じで書こうと思います。

コンテンツ

  • pingを使用して測定する方法 (有効なオプションなどの紹介)
    ※一部は他のページへのリンクとします。
  • 測定結果の解釈方法
  • pingを使ってこんなこともできるよ、という紹介 (帯域測定など)

注意
筆者の実務経験に基づき、時に調べて書いていきますが誤りを含む可能性があります。
適宜、指摘いただければ修正します。

目次

pingに関する基礎知識

最初に簡単にpingについて紹介します。前置きなので、知っている方は飛ばしてください。

通信に関する測定指標

通信に関する試験・測定を行うとき、必ず出てくる通信品質指標が3つあります。

  • 通信帯域 (スループット)
  • ロス率
  • 遅延

通信品質を図るとき、通信が間に入るシステムの評価を行うとき、など
様々な場面で上記の測定が求められます。

pingとはなにか?

上記の3指標のうち、特に遅延を測定できるツールが pingです。
ただし、pingで測れるのは往復遅延=RTT(Round Trip Time)のみです。

内部的にはICMPというプロトコルを使用しています。
こまかな話は以下のサイトを見てもらえれば分かると思います。

端的には宛先を決めて通信を発生させて、往復遅延(RTT)を測るツールだと思ってください。

往復遅延と片道遅延

ざっくりと、片道遅延の方が精密な測定だと理解してください。

  • 往復遅延(RTT):送信したデータが相手に届いて、相手からの応答が返ってくるまでの時間
  • 片道遅延:送信したデータが相手に届くまでの時間

往路(行き)・復路(帰り)の環境が異なる場合、片道遅延を測らないと通信の実態が分かりません。

例えば以下の様なイメージです。

  • モバイル回線は上下で帯域の割合が異なる設定になっていることが多い
  • インターネットは上りと下りで影響が読めない

本当に正確な測定をしたい場合は片道遅延で上り・下りを区別した方が良いです。
が、実態としては、研究業務でもない限りそこまでは追究しないことが多いです。

ということで、多くの人は往復遅延(RTT)を測定できれば十分かと思います。

pingの使い方

WindowsもLinuxも共通です。
コマンドラインにて以下を実行します。

ping [オプション] 送信先
  • 送信先:IPアドレス or ホスト名
  • オプション(なしでも動く):pingの動作を変更するオプション

使い方の例

疎通確認のためによくやるのが、googleへのping応答の確認です。

ping 8.8.8.8

※8.8.8.8はgoogleのDNSサーバのIPアドレスです。
googleはインターネット上にサーバを構えているので、上記が正しく通ればインターネットに接続できていることになります。

結果の見方

成功した場合、以下のような結果が表示されます。

ping 8.8.8.8
""" 応答(Windowsの場合)
8.8.8.8 に ping を送信しています 32 バイトのデータ:
8.8.8.8 からの応答: バイト数 =32 時間 =11ms TTL=117
8.8.8.8 からの応答: バイト数 =32 時間 =12ms TTL=117
8.8.8.8 からの応答: バイト数 =32 時間 =8ms TTL=117
8.8.8.8 からの応答: バイト数 =32 時間 =9ms TTL=117

8.8.8.8 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 8ms、最大 = 12ms、平均 = 10ms
"""
Ubuntuの場合
ping 8.8.8.8 -c 3
""" 応答(Ubuntuの場合)
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=13.4 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=15.1 ms
64 bytes from 8.8.8.8: icmp_seq=3 ttl=116 time=9.90 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 9.901/12.776/15.054/2.145 ms
"""

Linuxの人は-cオプションで指定した回数だけpingを送信します。オプションをつけないとCtrl+Cで終了するまで続けます。

失敗した場合、以下のような結果が表示されます。

ping 8.8.8.8
""" 応答(Windowsの場合)
8.8.8.8 に ping を送信しています 32 バイトのデータ:
一般エラー。
一般エラー。
一般エラー。
一般エラー。

8.8.8.8 の ping 統計:
    パケット数: 送信 = 4、受信 = 0、損失 = 4 (100% の損失)、
"""

とりあえずエラーという事だけは分かります…。

Ubuntuの場合
ping 8.8.8.8 -c 3
""" 応答(Ubuntuの場合)
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
From X.X.X.X icmp_seq=1 Destination Host Unreachable
From X.X.X.X icmp_seq=3 Destination Host Unreachable

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 0 received, +2 errors, 100% packet loss, time 2028ms
"""

Destination Host Unreachableとは、宛先ホストに到達できなかったことを意味します。

失敗した場合の対処としては、途中の経路までの疎通を確認します。
PC -> Wi-Fiルータ -> ルータ -> インターネット -> サーバ

  • まずはWi-Fiルータに疎通が通るかを確認、次にルータ…
  • インターネットの入口まで通るなら他のサーバへの疎通も試す

オプション

全て説明すると車輪の再発明になるので、公式のリンクを張ります。

  • Windowsの場合
    ※オプションの \ は - に置き換えてください。
  • Ubuntuの場合
    ※Linuxについては、公式ページのほかに以下が個人的に見やすかったです。

以降では、測定内容とオプションを紐づけて説明をしていきます。

pingの使い分け

pingのオプションを使い分けて、どのような測定ができるかを紹介します。
想定する測定のケースと、使用するオプションの紹介、結果の参照方法について記載します。

送信元のインターフェースを切り替える

想定するケース

  • 一つのPCで複数の経路(インターフェース)での通信品質を測定する
  • モバイル回線と有線回線の通信品質を比較する

※右のルートと左のルートの遅延を比較したい

使用するオプション

WindowsとLinux(Ubuntu)で異なります。

  • [Windowsの場合] -S オプションで送信元のIPアドレス指定する
ping -S インターフェースのIPアドレス 送信先
  • -Sの後にインターフェースのIPアドレスを記載してください
  • ipアドレスが分からない場合は ipconfig コマンドで確認できます
`ipconfig`コマンドの応答
ipconfig
""" 応答
イーサネット アダプター イーサネット:

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: xxxx::xxxx:xxxx:xxxx:xxxx
   IPv4 アドレス . . . . . . . . . . . .: XXX.XXX.XXX.XXX # <- これがIPアドレス
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   デフォルト ゲートウェイ . . . . . . .: XXX.XXX.XXX.XXX
"""
  • [Linuxの場合] -I pオプションで送信元のインターフェースを指定する
ping -I インターフェース名 送信先
  • -Iの後にインターフェース名を記載してください
  • インターフェース名が分からない場合は ip a コマンドで確認できます
`ip a` コマンドの応答
ip a
""" 応答
(中略)
#  enp0s3がインターフェース名
#   ↓
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether xx:xx:xx:xx:xx:xx brd ff:ff:ff:ff:ff:ff
    inet XXX.XXX.XXX.XXX/24 brd XXX.XXX.XXX.255 scope global noprefixroute enp0s3
       valid_lft forever preferred_lft forever
    inet6 xxxx::xxxx:xxxx:xxxx:xxxx/64 scope global temporary dynamic
       valid_lft 299sec preferred_lft 299sec
    inet6 xxxx::xxxx:xxxx:xxxx:xxxx:718f:86d/64 scope global dynamic mngtmpaddr noprefixroute
       valid_lft 299sec preferred_lft 299sec
    inet6 xxxx::xxxx:xxxx:xxxx:xxxx/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
"""

結果の参照

インターフェースの切り替えの効果を実感するために、以下の2ケースの結果を記載します。

成功するパターン:IF1->通信機器

ping 192.168.1.1 -S 192.168.101.30
"""
192.168.1.1 に ping を送信しています 192.168.101.30 から 32 バイトのデータ:
192.168.1.1 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.1 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.1 からの応答: バイト数 =32 時間 =1ms TTL=64
192.168.1.1 からの応答: バイト数 =32 時間 =1ms TTL=64

192.168.1.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 1ms、最大 = 1ms、平均 = 1ms
"""

192.168.101.1 と 192.168.101.30 は同じネットワークに属しているので、正常に通信できます。

失敗するパターン:IF2 -> ???

ping 192.168.1.1 -S 192.168.0.30
"""
192.168.1.1 に ping を送信しています 192.168.0.30 から 32 バイトのデータ:
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。

192.168.1.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 0、損失 = 4 (100% の損失)、
"""

タイムアウトしてパケットが損失してしまいます。

確かにインターフェースが切り替わっています。

測定時間と間隔の変更

Linux限定のオプションです。
どうやらWindowsでは実現できない様子…(たぶん)

想定するケース

  • 長時間測定をするために、間隔を長くする
  • より精密に細かく品質測定をしたい

使用するオプション

  • [Linux限定]-iオプションで送信間隔を、-wで測定時間を指定する
ping -i 送信間隔() -w 測定時間() 送信先

結果の参照

送信間隔を3秒、測定時間を15秒にしてみます。
結果が分かりやすいようにタイムスタンプをつける-Dオプションもつけます。

ping -i 3 -w 15 8.8.8.8 -D
""" 応答
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
[1704548001.603734] 64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=12.1 ms
[1704548004.604852] 64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=15.2 ms
[1704548007.606764] 64 bytes from 8.8.8.8: icmp_seq=3 ttl=116 time=12.8 ms
[1704548010.692587] 64 bytes from 8.8.8.8: icmp_seq=4 ttl=116 time=59.0 ms
[1704548013.607301] 64 bytes from 8.8.8.8: icmp_seq=5 ttl=116 time=10.4 ms

--- 8.8.8.8 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 12015ms
rtt min/avg/max/mdev = 10.426/21.896/58.987/18.607 ms
"""

3秒間隔で15秒継続なので、確かに5回送信しているようです。

ping応用方法の紹介

毎行にタイムスタンプを付与する

想定するケース

  • pingの結果を解析したい。いつ遅延が大きくなったか分からないと困る。
    ※起こした現象と遅延を紐づける必要がある(パケット量の遅延への影響測定など)
  • ping + iperf で通信結果を解析したい。けど、時間情報がないと同期が取れない
    pingにはデフォルトで時間情報がつかないので、非常に頻発するケースです。

使用するオプション

WindowsとLinux(Ubuntu)で異なります。Windowsは少し工夫が必要です。

  • [Windowsの場合/powershell限定] 無理やり時間情報を付与する
ping 送信先 | %{(Get-Date).ToString() + " $_"}

※(Get-Date).ToString()で時間情報を出力し、その後ろにpingの結果をつけています。

  • [Linuxの場合] -D オプションを使用する
ping -D 送信先

※epoch秒の形式でタイムスタンプがつきます。

結果の参照

  • Windowsの場合
ping 8.8.8.8 | %{(Get-Date).ToString() + " $_"}
""" 応答
2024/01/06 23:05:10
2024/01/06 23:05:10 8.8.8.8 に ping を送信しています 32 バイトのデータ:
2024/01/06 23:05:10 8.8.8.8 からの応答: バイト数 =32 時間 =12ms TTL=117
2024/01/06 23:05:11 8.8.8.8 からの応答: バイト数 =32 時間 =10ms TTL=117
2024/01/06 23:05:12 8.8.8.8 からの応答: バイト数 =32 時間 =16ms TTL=117
2024/01/06 23:05:13 8.8.8.8 からの応答: バイト数 =32 時間 =10ms TTL=117
2024/01/06 23:05:13
2024/01/06 23:05:13 8.8.8.8 の ping 統計:
2024/01/06 23:05:13     パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
2024/01/06 23:05:13 ラウンド トリップの概算時間 (ミリ秒):
2024/01/06 23:05:13     最小 = 10ms、最大 = 16ms、平均 = 12ms
"""

無理やりタイムスタンプをつけているので、すべての行にタイムスタンプがついています…。

  • Linuxの場合
ping -D 8.8.8.8 -c 3
""" 応答
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
[1704550109.575467] 64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=9.87 ms
[1704550110.610034] 64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=43.2 ms
[1704550111.591852] 64 bytes from 8.8.8.8: icmp_seq=3 ttl=116 time=23.3 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2003ms
rtt min/avg/max/mdev = 9.873/25.454/43.236/13.709 ms
"""

こちらは結果にだけタイムスタンプがつきます。

遅延が大きすぎて結果が図れない状況を打破する

想定するケース

  • 遅延が大きい環境で測定すると、実際の遅延でなくエラーしか取れない
    pingのデフォルトタイムアウトは4秒です。このため4秒以上の遅延は測定できません

使用するオプション

タイムアウトをオプションで変更します。WindowsとLinux(Ubuntu)で異なります。

  • [Windowsの場合] -w オプションを使用する
ping -w タイムアウト(ミリ秒) 送信先
  • [Linuxの場合] -W オプションを使用する
ping -W タイムアウト() 送信先

結果の参照

とくになし。応答を待つ時間が伸びます。

pingで帯域も測定する

想定するケース

  • とにかく簡単に帯域が測りたい
  • iperfサーバを立てられない
    ちょっとした裏技に近い内容です。ちょっと調べたら出てきますが…。
    ただし、用法に注意があります。こちらは本節の最後に記載します。

使用するオプション

オプションを使用して送信するデータのバイト数を変更します。
WindowsとLinux(Ubuntu)で異なります。動作はどちらも同じです。

  • [Windowsの場合] -l オプションを使用する
ping -l バイト数 送信先

※最大65500バイトまで指定できます。

  • [Linuxの場合] -s オプションを使用する
ping -s バイト数 送信先

※最大65507バイトまで指定できます。

結果の参照

Wi-Fiルータへpingを送信してみます。まずは、デフォルトのバイト数で送信します。

ping 192.168.0.1
""" 応答
192.168.0.1 に ping を送信しています 32 バイトのデータ:
192.168.0.1 からの応答: バイト数 =32 時間 =5ms TTL=64
192.168.0.1 からの応答: バイト数 =32 時間 =8ms TTL=64
192.168.0.1 からの応答: バイト数 =32 時間 =6ms TTL=64
192.168.0.1 からの応答: バイト数 =32 時間 =8ms TTL=64

192.168.0.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 5ms、最大 = 8ms、平均 = 6ms
"""

32Byteの場合、数msで応答が返ります。ただし、バイト数が32バイト程度の少量だと、帯域の測定では誤差が大きくなる可能性があるので、バイト数を増やしてみます。
Windows最大値の65500Byteで送信してみます。

ping -l 65500 192.168.0.1
""" 応答
192.168.0.1 に ping を送信しています 65500 バイトのデータ:
192.168.0.1 からの応答: バイト数 =65500 時間 =28ms TTL=64
192.168.0.1 からの応答: バイト数 =65500 時間 =16ms TTL=64
192.168.0.1 からの応答: バイト数 =65500 時間 =20ms TTL=64
192.168.0.1 からの応答: バイト数 =65500 時間 =20ms TTL=64

192.168.0.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 16ms、最大 = 28ms、平均 = 21ms
"""

平均21msです。32Byteの時と比べて、遅延が大きくなっています。ここで、簡単な計算をしてみます。
通信帯域は 通信量[バイト数] / (通信時間[秒]/2) で求められます。
通信時間を2で割っているのは、往路復路が同じ環境であると想定して片道の通信時間を求めるためです。

通信帯域 = 65500 * 8 / (0.021 / 2) = 49.9Mbps

今回は49.9Mbpsという結果が出てきました。
(なんだか思ったより仕事部屋の環境が遅くてびっくり…)

なお、測定した往復遅延(RTT)には単純な帯域由来の遅延のほかに、通信経路上の遅延が含まれます。

測定した遅延 = 通信帯域による遅延 + 通信経路の遅延

このため、もう少し厳密にやるなら2回測定した上で差分を取ります。
例えば半分のバイト数32750Byteで往復時間を測定し、その差分から帯域を求めます。

ping -l 32750 192.168.0.1
""" 応答
192.168.0.1 に ping を送信しています 32750 バイトのデータ:
192.168.0.1 からの応答: バイト数 =32750 時間 =11ms TTL=64
192.168.0.1 からの応答: バイト数 =32750 時間 =12ms TTL=64
192.168.0.1 からの応答: バイト数 =32750 時間 =13ms TTL=64
192.168.0.1 からの応答: バイト数 =32750 時間 =10ms TTL=64

192.168.0.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 4、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 10ms、最大 = 13ms、平均 = 11ms
"""

ここで、
65500バイトの遅延 = 帯域が65500バイトを処理する遅延 + 通信経路の遅延
32750バイトの遅延 = 帯域が32750バイトを処理する遅延 + 通信経路の遅延

なので、
65500バイトの遅延 - 32750バイトの遅延 = 帯域が32750バイトを処理する遅延

すなわち、往復遅延の差分となる 32750バイト と 10ms で帯域を求めます。

帯域 = (65500 - 32750) * 8 / {(0.021-0.011)/2} = 52.4Mbps

ということで、結果としては52.4Mbpsとなります。
ただ、差分を取る方法も時々刻々と状況が変化している場合、あまり精度が出ません。本当に精密に測りたいならiperfを使ったほうが良いです。

この方法で帯域を測る場合の注意をいくつか記載します。

  • まず、自分の運用するサーバや機器以外に65500バイトなどの大容量pingを飛ばしてはいけません
    • サーバ負荷を上げてしまい、迷惑をかけることになります。(やられた側からするとDos攻撃みたいなものです)
    • そもそも、大きなバイト数のpingは攻撃とみなされ遮断されることがあります。(この場合、応答は返りません)
    • なので、測定時は自分の運用するサーバや機器に対して行ってください。
  • この方法では往路と復路が同等の通信環境であることを仮定します
    • 上りと下りを分けての測定はできません
    • 上りと下りで大きく帯域が異なる場合、平均化されてしまいます。

上記の通り、色々と制約はあります。経路上や終端にpingに応答する自前のサーバや機器があり、帯域を手軽に測りたいときには便利です。

なによりiperfサーバを立てずに済むので、ログインできない通信機器を使用しての測定が可能です。

また、インターネット環境に繋がない閉じたネットワークでは、iperfの導入も難しいことがあります。そのような環境下で、帯域の変化を捉えるために使う、なんてこともできます。

おわりに

また長くなってしまった。pingは意外と奥が深いですね。
次記事書くなら、測定データをマージするスクリプトなど公開したいな、と思います。

今回もお付き合いいただきありがとうございました。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?