【PC】Android で UDPマルチキャスト
Androidで UDPのマルチキャスト(ブロードキャスト)を行うというキーワードで検索すると、当ブログが検索結果として出てくるようで、たぶんサンプルソースコードを期待して来訪される方が大変多い。たしかにサンプルコードを探してみると、ものすごく少ないので掲載しておくことにする。
実は、はてなダイアリーからはてなブログになって半月ほど経過するが、HTMLを使えるとはいえ、はてな記法なんかも魅力的だったりして、その意味では未だに、はてなブログは非力だ。もちろんCSSを駆使しHTMLを書けばいいのだろうが、毎日毎日書くブログがそんなことでは不便で仕方がない。さらなる、はてなブログの進化を待ちながら、ソースコード掲載の練習も兼ねてたりして・・・
package ***.***.****; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket; import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.net.SocketException; import java.util.concurrent.TimeUnit; import android.net.DhcpInfo; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.Bundle; import android.app.Activity; import android.content.Context; public class UDPMulitiCast extends Activity { //============================================= // // UDPポート(マルチキャスト送信用)と // TCPポート(受信用) // public final static int UDPPORT = 7777; public final static int TCPPORT = 8888; //============================================= // // スレッド管理用 // private static Thread udpmuliticastThread = null; private static Thread tcpreceiveThread = null; //============================================= // // TCP受信用 // private ServerSocket serverSocket; private Socket socket; //============================================= // // サーバーのIPアドレス( UDPマルチキャストを受けたら // TCPで返信があるという前提) // private static String serverIP = null; //============================================= // // コンストラクタ // @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_udpmuliti_cast); //============================================= // // UDPマルチキャストを投げつけるスレッドを開始する // if ( udpmuliticastThread == null){ udpmuliticastThread =new Thread( new Runnable() { public void run() { sendUDP(); } } ); udpmuliticastThread.start(); } //============================================= // // TCP受信用のスレッドを開始する // if ( tcpreceiveThread == null){ tcpreceiveThread =new Thread( new Runnable() { public void run() { receiveTcp(); } } ); tcpreceiveThread.start(); } } //============================================= // // UDPマルチキャストを投げつけるスレッド本体 // private void sendUDP(){ Thread thread = Thread.currentThread(); // // serverIP が確定するまで繰り返す // while( serverIP == null && udpmuliticastThread == thread ){ String msgStr = getMyAddress( this ); DatagramSocket udpSocket; try { udpSocket = new DatagramSocket( UDPPORT ); udpSocket.setBroadcast(true); DatagramPacket packet; packet = new DatagramPacket(msgStr.getBytes(), msgStr.length(), getBroadcastAddress( this ), UDPPORT); udpSocket.send(packet); udpSocket.close(); } catch (SocketException e1) { } catch (IOException e1) { } //5秒待つ try { TimeUnit.MILLISECONDS.sleep(5000); } catch (InterruptedException e) { } // サーバーからTCPでの返答があり // サーバーIPアドレスが判明するまで続ける } } //============================================= // // 自機の(Wifiの) IPアドレスを取得 // public String getMyAddress( Context context ){ String strIp = "0.0.0.0"; try { WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); WifiInfo wifiInfo = wifiManager.getConnectionInfo(); int ip = wifiInfo.getIpAddress(); strIp = ((ip >> 0) & 0xFF)+"."+ ((ip >> 8) & 0xFF)+"."+ ((ip >> 16) & 0xFF)+"."+ ((ip >> 24) & 0xFF); } catch (Exception e) { } return strIp; } //============================================= // // Muliticast用のアドレスを取得 // public InetAddress getBroadcastAddress( Context context ) throws IOException { WifiManager wifiManager = (WifiManager)context.getSystemService(Context.WIFI_SERVICE); DhcpInfo dhcp = wifiManager.getDhcpInfo(); int broadcast = (dhcp.ipAddress & dhcp.netmask) | ~dhcp.netmask; byte[] quads = new byte[4]; for (int k = 0; k < 4; k++) quads[k] = (byte) ((broadcast >> k * 8) & 0xFF); return InetAddress.getByAddress(quads); } //============================================= // // TCP受信用スレッド本体 // private void receiveTcp() { Thread thread = Thread.currentThread(); try { serverSocket = new ServerSocket( TCPPORT ); while( thread == tcpreceiveThread ){ socket = serverSocket.accept(); BufferedReader br = new BufferedReader( new InputStreamReader(socket.getInputStream())); String str; while( (str = br.readLine()) != null && thread == tcpreceiveThread ){ serverIP = str; } if( socket != null){ socket.close(); socket = null; } } } catch (IOException e) { } finally { try { // 接続終了処理 tcpreceiveThread = null; if( serverSocket!=null){ serverSocket.close(); } if( in!=null ){ in.close(); } if( socket!=null ){ socket.close(); } } catch (IOException e) { } } } }
ハイライト表示になってくれるのはありがたいけれど、なんか思ったように表示してくれないなぁ。そんなこんなで、時間がなくなったのでソースの解説は省略させていただきます。。。
UDP でマルチキャストして
ほかの機械がそれを拾って、IPアドレスをTCPで送ってくる。
それを受け取る、というもの。
もう少しさわると、エコーサーバーとか、ミニチャットとか作れる元になるのがこれ。
実用には、 onStop 時の処理を考えないと、再度この Activity を利用すると、Socket がつくれなくなる(ポートが開きっぱなしだから)ので注意と、いろいろ工夫が必要。