ページ更新: 2005-08-28 (日) (4371日前)
[編集]

J2SE 5.0 #

pingを行うメソッドが追加された。

[編集]

J2SE 1.4まで #

Javaでpingやるかもしれないので、調べてみた。

C言語での実装は、 C MAGAZINE 2003年7月号 http://www.cmagazine.jp/contents/200307.html の 特集2が使えるかも。

実装するだけなら、こうやるよなあ、たぶん。

  1. C++でpingのコードを作成し、
  2. JavaからJNIで呼ぶ。

でも、Linuxでは /bin/ping ってrootにsuidしてある→root権限が必要なわけで、 これをJavaから解決するのは大変ではないかな。 (推測だが、Echo Reply受信にroot権限が必要なのかも。)

  • 補足
    Java の Socket オプション によると:
    Java ではサポートされていない、使用可能な BSD オプションは次のとおりです。
    
    * RAW/ICMP SOCKETS:
      このオプションを使用する理由として、Java で ping を記述できるという点があるが、
      それによってセキュリティ上の問題が発生する可能性がある。 UNIX コンピュータ上の
      root でなければならない 

/bin/pingをstrace, ltraceで観察。

# strace ping 127.0.0.1
  : (略)
socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
getuid32()                              = 0
setuid32(0)                             = 0
getpid()                                = 17416
setsockopt(3, SOL_SOCKET, SO_BROADCAST, [1], 4) = 0
setsockopt(3, SOL_SOCKET, SO_RCVBUF, [49152], 4) = 0

# ltrace /bin/ping 127.0.0.1
__libc_start_main(0x08048d50, 2, 0xbffffb34, 0x080489cc, 0x0804a7c0 <unfinished ..
.>
__register_frame_info(0x0804c560, 0x0804c718, 0xbffffad8, 0x40046f18, 0x40132e48)
= 0x08048a24
getuid()                                          = 0
getprotobyname("icmp")                            = 0x40135f28
socket(2, 3, 1)                                   = 3
getuid()                                          = 0
setuid(0)                                         = 0
getopt(2, 0xbffffb34, "I:LRc:dfh:i:l:np:qrs:t:v") = -1
inet_aton("127.0.0.1", 0x0805c908)                = 1
malloc(192)                                       = 0x0805d958
getpid()                                          = 17424
setsockopt(3, 1, 6, 0xbffffa3c, 4)                = 0
setsockopt(3, 1, 8, 0xbffffa3c, 4)                = 0
inet_ntoa(0x0100007f)                             = "127.0.0.1"
printf("PING %s (%s): %d data bytes\n", "127.0.0.1", "127.0.0.1", 56PING 127.0.0.1
 (127.0.0.1): 56 data bytes
) = 42

java.net.SocketImplやjava.net.PlainSocketImplのソースコードを みてみたが、ICMPをあつかえるほどに仮想化されているかどうか、わからない。

J2SDK 1.4.2_03のコードでは、Socketへのアクセスはjava.io.FileDescriptor経由で 行われ、java.net.PlainSocketImplではOS依存の部分はnativeメソッドになっている。

Googleで 'java icmp'を検索したところ、http://w6.loria.fr/software/JDKv6/って ページを発見。 これはIPv6の実装だが、この中のjava.net.IcmpPacket/IcmpSocketという クラスでping (ICMP Echo Request/Reply) を実現できるかもしれない。

もっとも、IPv6自体はJ2SE 1.4で実装されているようなので、今後このコードは メンテナンスされないかも。

teamlinux.org.uk: saxm
http://www.teamlinux.org.uk/saxm/projects/icmp/

  • Javaでのpingの実装。対象OSはUnix系みたい (libping.soがあるので)