読者です 読者をやめる 読者になる 読者になる

UDP で How are you? な挨拶をしてみた

何だか知らないけど、"How are you?" の会話を UDP でやってみた。
How are you? って訊かれたら、I'm fine thank you. and you? って返せって英語の時間に教わったと思うけど、
Good! とか not bad とかって返すのがいいらしい。
まー、そんな感じ。あ、非同期なのでよろしく〜。

最初は Guest 側から〜。

        public void run(string[] args) {
            int listen_port = 2000;
            //IPHostEntry host = Dns.GetHostEntry( Dns.GetHostName() );
            //Stack<IPAddress> address_stack = new Stack<IPAddress>( host.AddressList );
            //IPEndPoint remote_point = new IPEndPoint( address_stack.Pop(), listen_port );
            // 受信から始めるときは、IP アドレスに Any(0.0.0.0) を入れておきます。
            IPEndPoint listen_point = new IPEndPoint( IPAddress.Any, listen_port );

IPAddress.Any と 送信先のポート番号を入れたエンドポイントを作成してるよ。
ポート番号は、0 でもいいのかな〜とか思ったんだけど、ダメらしい。

            UdpClient client = new UdpClient( listen_point );
            Encoding encoding = Encoding.UTF8;
            string greeting = string.Empty;
            string segment = string.Empty;
            byte[] send_bytes = null;
            int times = 0;

UDP 通信に必要な変数を宣言してるよ。
greeting が、送信する挨拶用の文字列、segment が受信した文字列かな〜。
あとは名前で分かるよね?

            while ( true ) {
                /*
                 * Guest は bob。
                 */
                Console.Write( "alice > " );
                IAsyncResult done = client.BeginReceive( receiveCompleted, null );

                while ( !messageReceived ) {
                    Thread.Sleep( 100 );
                }

受信するときは、connect メソッドとか要らないよ〜。
いきなり receive でおk。
ここで、受信できるまで、 while ブロックで待つんだけど、messageReceived って何よ?ってことにならない?
これはね、static な bool 型の変数だよ。
どう使ってるかっていうと:

        public void receiveCompleted(IAsyncResult ar) {
            messageReceived = true;
        }

このメソッドが呼び出された時、受信は既に終わっているんだ…。
じゃないけど、そんな感じ。
なので、messageReceived を真にして、待機ループを脱出しようとしてる。
ということで次。

                //segment = encoding.GetString( client.EndReceive( done, ref listen_point ) );
                // listen_point には受信した IP アドレスとポート番号が入ります。
                segment = encoding.GetString( client.EndReceive( done, ref listen_point ) );
                Console.WriteLine( segment );

脱出してから受信を終了するよ。
それで返ってくるのはバイト列なので、それをエンコードして文字列にして、それを表示するだけ。

                if ( segment.StartsWith( "bye" ) )
                    break;

プログラムをいつ終わるかって考えてみたときに、"bye" が来たら終了ってことでいいかな〜と思ったので、
そーいうことにしてる。
ということで次〜。

                Thread.Sleep( 1000 );

                if ( segment.EndsWith( "How are you?" ) ) {
                    Random r = new Random();
                    int index = r.Next( CONDITIONS.Length );

                    greeting = string.Format( "{0} Thanks. How are you?", CONDITIONS[index] );
                } else {
                    greeting = "over.";
                }

1 秒寝て、ここで、挨拶の中身を考えるよ。
ボブ*1の現在の状態を乱数で決定するよ。
それ以外なら over. にする。
めっさ簡単でしょ?

送信の方はまた明日〜。
おっと、全ソースはここ[github.com]で覧れるよ〜。

*1:ここではホストがアリスで、受信先がボブってことにしてあるんだ