package lecture.threadAndComm;

import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;

import lecture.common.Log;
import lecture.common.Util;


//
/**
 * サーバー認識のサンプル Java
 *
 * 通信処理では、常に「通信相手をどのようにして見つけるか」という問題が発生する
 * そのため、本来の通信処理の前に、通信相手を見つけることが必要
 *
 * 通信相手がIP:ポート番号ともに完全固定であれば、問題はないが、このようなシステムは柔軟性がない
 *
 * 多くは当該ホストを見つけるためのポート番号が定義されていて、このポートに対してブロードキャストを行う
 * 該当するホストは、当該サービスのポート番号を返信する
 * 注、該当するホストのIPは返信を受信すれば自動的に分かる
 */
interface Const {
  public static String MSG = "XXXX Process BroadCastPort=";
  /**
   * ブロードキャスト用のポート番号
   * 1024以降の他のアプリで使用していない番号を指定する
   */
  public static int BROAD_CAST_PORT = 5555;
}

/** サーバー */
class FindServerServer {
  /** サーバーがサービスを受け付けるポート番号 */
  private static final int SERVICE_PORT = 6666;
  public static void main(String[] args) {
    //
    // クライアントからの接続を受け付けるスレッドを起ち上げておく
    // ポート番号はSERVICE_PORTを使用する
    // 当サンプルのテーマではないので、上記は省略
    //
    // サーバーの所在を知らせるブロードキャストを行う
    DatagramSocket socket = null;
    try {
      InetSocketAddress inetAddr = new InetSocketAddress("255.255.255.255",Const.BROAD_CAST_PORT);
      byte[] buffer = (Const.MSG+SERVICE_PORT).getBytes();
      DatagramPacket packet = new DatagramPacket(buffer,buffer.length,inetAddr);
      socket = new DatagramSocket();
      for (;;) {
        socket.send( packet );
        Log.print("broadcast..");
        // 5sec待つ
        Util.sleep(5000);
      }
    }
    catch(Exception ex) {
      ex.printStackTrace();
    }
    finally {
      if (socket != null) {
        socket.close();
      }
    }
  }
}
/** クライアント */
class FindServerClient {
  public static void main(String[] args) {
    DatagramSocket dgSocket = null;
    try {
      dgSocket = new DatagramSocket(Const.BROAD_CAST_PORT);
      byte buffer[] = new byte[1024];
      DatagramPacket packet = new DatagramPacket(buffer,buffer.length);
      for (;;) {
        dgSocket.receive(packet);
        String str = new String(buffer);
        if (str.startsWith(Const.MSG)) {
          // サーバーのアドレスとポート番号を取得
          String portStr = str.substring(Const.MSG.length()).trim();
          int port = Integer.parseInt(portStr);
          Log.print("port="+port);
          InetAddress inetAddr = packet.getAddress();
          Log.print("server="+inetAddr.toString().substring(1));
          //
          // サーバーとの接続処理を行う
          // 当サンプルのテーマではないので省略
          break;
        }
        // 目的のサーバーからの受信ではなかったので、再度受信する
      }
    }
    catch(Exception ex) {
      ex.printStackTrace();
    }
    finally {
      if (dgSocket != null) {
        dgSocket.close();
      }
    }
  }
}
//---------------------------------------------------
//・目次 - スレッドと通信
//http://blogs.yahoo.co.jp/artery2020/40575722.html
//・目次 - Java入門
//http://blogs.yahoo.co.jp/artery2020/39975776.html
//・目次 - ビジネスパーソンの常識と非常識
//http://blogs.yahoo.co.jp/artery2020/39728331.html
//・目次 - 論理・発想・思考についての考察と鍛え方
//http://blogs.yahoo.co.jp/artery2020/39657784.html
//---------------------------------------------------