C# で TCP ってみた

UDP に引き続き、TCP やってみたよ〜。
ということで、System.Net 名前空間と System.Net.Sockets 名前空間は外せないねっ!

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;

他のは窓魔術を扱ったり扱わなかったりでいれてる。
System.Threading 名前空間は要らないかも。
ということで、次。

        /// <summary>
        ///
        /// </summary>
        /// <param name="text"></param>
        private void set_text_setter(string text) {
            StringBuilder resulttext_builder = new StringBuilder( tbResult.Text );

            resulttext_builder.AppendLine( text );
            tbResult.Text = resulttext_builder.ToString();
        }

結果をテキストボックスに書き込みそうな関数。
+ でくっつけるのはかっこ悪いよね〜
で、次。

        /// <summary>
        ///
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="ergs"></param>
        private void btnSend_Click(object sender, EventArgs ergs) {
            TcpClient client = new TcpClient( AddressFamily.InterNetwork );
            NetworkStream stream = null;

            set_text_setter( "送信ボタンが押されました。" );

とりあえず、TcpClient オブジェクトを作成するよ!!

                IPAddress ip_address;

                if ( tbDstIpAddress.Text == String.Empty ) {
                    IPHostEntry host = Dns.GetHostEntry( Dns.GetHostName() );
                    Stack<IPAddress> address_stack = new Stack<IPAddress>( host.AddressList );
                    // 0 番は IPv6 なので、IPv4 の IP アドレスにする。
                    ip_address = address_stack.Pop();
                } else
                    ip_address = IPAddress.Parse( tbDstIpAddress.Text );

                int port = Convert.ToInt32( tbDstPort.Text );
                IPEndPoint endpoint = new IPEndPoint( ip_address, port );

                client.Connect( endpoint );

tbDstIpAddress はテキストボックスで、送信先の IP アドレスをいれとくやつだよ。
これが、空文字の時はローカルの IP アドレスを取得するよ!!
AddressList は IPAddress の配列なんだけど、私がやったときは IPv4IPv6 の 2 つが入ってて、
まー、めんどくさいのでスタックに入れて、pop することにした。
これは、IPv4 のアドレスが末尾に入ってるからなんだけどね。

それ以外なら、テキストボックスの中身を IP アドレスにパースするよっ!
無事に IP アドレスを取得できたら、ポート番号を数値に変換したりして connect するんだ。
よーし、次。

                stream = client.GetStream();

                if ( stream.CanWrite ) {
                    string send_text = string.Format( "<request><get version=\"{0}\">/</get><host>{1}</host></request>",
                                                      1.1,
                                                      tbDstIpAddress.Text
                                                      );
                    byte[] send_bytes = Encoding.UTF8.GetBytes( send_text );

                    stream.Write( send_bytes, 0, send_bytes.Length );
                }

UDP だと、普通に書き込んだり読み込んだりするんだけど、TCP の場合は NetworkStream オブジェクトから読んだり書き込んだりするんだ。
もしかしたら…ということで、CanWrite で書き込めるかどうか調べてから書き込む。

                if ( stream.CanRead ) {
                    client.ReceiveBufferSize = 256;

                    byte[] received_bytes = new byte[client.ReceiveBufferSize];
                    int received_bytes_amount;
                    string received_text = string.Empty;

                    received_bytes_amount = stream.Read( received_bytes, 0, received_bytes.Length );
                    received_text = Encoding.UTF8.GetString( received_bytes,
                                                             0,
                                                             received_bytes_amount
                                                             );
                    set_text_setter( received_text );
                }

送信したので、今度は受信する。
受信した文字列をテキストボックスに吐き出して終了。

                if ( stream.CanRead ) {
                    client.ReceiveBufferSize = 256;

                    byte[] received_bytes = new byte[client.ReceiveBufferSize];
                    int received_bytes_amount;
                    string received_text = string.Empty;

                    received_bytes_amount = stream.Read( received_bytes, 0, received_bytes.Length );
                    received_text = Encoding.UTF8.GetString( received_bytes,
                                                             0,
                                                             received_bytes_amount
                                                             );
                    set_text_setter( received_text );
                }

おつかれさまでした〜。
全文*1ここ[github.com] にあるよ。

*1:じゃないけど