ICMPならpingを打てばよいし、HTTP、HTTPS、SSH、TELNETなどならブラウザやteratermで実際にアクセスしてみればいい。TCPならtelnetでポート指定すればよいが、UDPの特定のポートの通信を発生させるためにはツールを使っていた。ipsendwinとか、iperfとか。 ixiaのトラフィックジェネレータを使ったこともある。
最近もipsendwinを使ったのだが、もう古いソフトで、Vectorのダウンロード画面ではサポートOSに「Windows XP/Me/2000/NT/98/95」と書いてある。 そしてあるPCでは「winpcap.dllがない」と表示され、コピーするもまた違うdllがない、エントリポイントが見つからない、などどいうことで実行するのをあきらめた。
そして、このご時世、いろんなアプリやスクリプトがあるし、「UDP 1234のパケットを特定のIPアドレスに10個ほど送信する」なんてことは簡単にできるんじゃないのかと思った。
pythonとかjavascriptとかさらっと調べたが、結局javaでやった。
java。 ちょっと、今更java?みたいな感じがした。 javaで簡単なプログラムを書いたことはあり、 簡単に書けて「ネットワークプログラミングならjavaだな」と思った。
しかし、javaは当然インストールされているだろうと思って普段仕事でつかっているPCのコントロールパネルを見たがjavaがインストールされていない。 たしかコントロールパネルにjavaのアイコンがあったはず.... もう最近はjavaが使われなくなりつつあるのか?
というわけでjavaのインストールから始める。 「java ダウンロード」などで検索するとダウンロードページがすぐ出てくるが、 32ビット版をインストールするように導かれる。 今なら、Version 8 Update 241 64ビット版もあるようだがどういうことだろうと少し調べたら、 ブラウザが32ビット版がデフォルトなのでjavaも32ビット版を使え、ということだった。
https://java.com/ja/download/faq/java_win64bit.xml
普段はクロームを使っているが64ビット版である。 が、たしかクロームでjavaが使えなくなったんじゃなかったっけ...?
IEはたしかに32ビット版のようである。使っていないが。 javaのランタイムは32ビット版のインストールページが検索すると上位に表示されるが、 開発環境、jdkだと13.0.2の64ビット版が出てくる。
32ビット版のランタイムがインストールされているところに64ビット版のjdkをインストールすると、実行時にエラーになる。 ランタイムは入れず、入っていたらアンインストールし、64ビット版のjdkをインストールする。 インストールしたら、binフォルダへのpathを登録する。
C:\Program Files\Java\jdk-13.0.2\bin
pathを登録したらコマンドプロンプトを開いてバージョンを確認してみる。
C:\WINDOWS\system32>javac -version javac 13.0.2
HelloWorld.java を作る。
public class HelloWorld{ public static void main(String[] args){ System.out.println("Hello World!!"); } }
javac HelloWorld.java
でコンパイル。 HelloWorld.class ができる。
実行。
C:\WINDOWS\system32>java HelloWorld Hello World!!
では、UDPの任意のパケットを送信するプログラムを書こう。
Client.java
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetSocketAddress; public class Client { public static void main(String[] args) throws IOException { String sendData = "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"; byte[] data = sendData.getBytes("UTF-8"); DatagramSocket sock = new DatagramSocket(); int count = Integer.parseInt(args[2]); String Host = args[0]; Integer DestPort = Integer.parseInt(args[1]); for(int i=1; i<=count; i++) { DatagramPacket packet = new DatagramPacket(data, data.length, new InetSocketAddress(Host,DestPort)); sock.send(packet); System.out.println("Sent UDP data "+Host+":"+DestPort); try{ Thread.sleep(1000); }catch(InterruptedException e){} } sock.close();// } }
使い方
java Client 宛先 ポート番号 パケット数
たとえば
java Client 192.168.1.1 12345 5
192.168.1.1宛に、UDP の宛先ポート12345のパケットを5個送信する。
間隔は1秒
送るだけならこれで終わり。 もし指定したIPアドレスのホストが存在しないと、arp解決されずパケットが送信されないだろう。 指定したIPアドレスのホストが存在すればパケットが送信されるが、 テキトーなポート宛に送っているので、port unreachableが返ってくるだろう。 送ったパケットを受信しそれを確認したい場合は受信側で下記を実行する。
Server.java
import java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.util.Arrays; public class Server { public static void main(String[] args) throws IOException { Integer Port = Integer.parseInt(args[0]); while (true) { DatagramSocket sock = new DatagramSocket(Port); byte[] data = new byte[1024]; DatagramPacket packet = new DatagramPacket(data, data.length); sock.receive(packet); System.out.println("Received :"+new String(Arrays.copyOf(packet.getData(),packet.getLength()),"UTF-8")); sock.close(); } } }
動作確認 Client.javaとServer.javaをコンパイルしたら、 コマンドプロンプトを二つ起動して、 Client.classとServer.classがあるフォルダに移動し、片側でサーバを起動するこのときポート番号を指定する。
C:\Users\sam\udp_data_send>java Server 12345
もう一方でクライアントを起動する。
C:\Users\sam\udp_data_send>java Client localhost 12345 10 Sent UDP data localhost:12345 Sent UDP data localhost:12345 Sent UDP data localhost:12345 Sent UDP data localhost:12345 Sent UDP data localhost:12345 Sent UDP data localhost:12345 Sent UDP data localhost:12345 Sent UDP data localhost:12345 Sent UDP data localhost:12345 Sent UDP data localhost:12345 C:\Users\sam\udp_data_send>java Server 12345 Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef Received :0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdefTCPはまた今度。