C#言語(3)-TCP通信(クライアント編)

このエントリーをはてなブックマークに追加

C#言語を使用して、TCP通信のアプリケーションを作成します。今回は、クライアント側のアプリケーションになります。TCP通信アプリケーションのダイアログは下記のようになります。

IPには、接続先アドレスを入力して、ポートには、使用するポート番号を入力します。IP、ポートは自分のPCの環境に合わせてください。私の場合は、IP「192.168.25.1」、ポート「8888」を入力しました。また、セキュリティソフトがインストールされている場合は、ネットワークに接続できるように、設定をして下さい。入力したら、開始ボタンをクリックする事で、接続を試みます。接続が完了したら、下記のようなメッセージが表示されます。

ソースコードは下記のようになります。※リスナー側との接続、データの送受信部分を抜粋。

private void Btn_Start_Click(object sender, EventArgs e)
{
    bStopFlg = false;
            
    //接続先IPアドレス
    string strAdd = GettxBoxIP();

    //接続先ポート番号
    //TcpListenerオブジェクトを作成する
    int port = int.Parse(GettxBoxPort());

    //TcpClientを作成し、サーバーと接続する
    tcp = new System.Net.Sockets.TcpClient(strAdd, port);
    SettxBoxReceive("サーバー(" + 
        ((System.Net.IPEndPoint)tcp.Client.RemoteEndPoint).Address + 
        ":" + ((System.Net.IPEndPoint)tcp.Client.RemoteEndPoint).Port + 
        ")と接続しました。");
    SettxBoxReceiveScrollEnd();

    ReceiveThread = new System.Threading.Thread(ReceiveStart);
    ReceiveThread.IsBackground = true;
    ReceiveThread.Start();
}

private void ReceiveStart()
{
    //クライアントから送られたデータを受信する
    System.Text.Encoding enc = System.Text.Encoding.UTF8;

    NetworkStream ns = null;

    //NetworkStreamを取得
    ns = tcp.GetStream();

    //タイムアウト設定
    ns.ReadTimeout = 10000;
    ns.WriteTimeout = 10000;

    do
    {
        System.IO.MemoryStream ms = new System.IO.MemoryStream();
        byte[] resBytes = new byte[256];
        int resSize = 0;

        do
        {
            try
            {
                //データの一部を受信する
                resSize = ns.Read(resBytes, 0, resBytes.Length);
            }
            catch (IOException e) { }

            //受信したデータを蓄積する
            ms.Write(resBytes, 0, resSize);

        } while (ns.DataAvailable);

        //受信したデータを文字列に変換
        string resMsg = enc.GetString(ms.GetBuffer(), 0, (int)ms.Length);
        ms.Close();
        //末尾の¥nを削除
        resMsg = resMsg.TrimEnd('¥n');
        if (resMsg != "")
        {
            Console.WriteLine(resMsg);
            SettxBoxReceive(GettxBoxReceive() + resMsg + "¥r¥n");

            SettxBoxReceiveScrollEnd();

        }
    } while (bStopFlg == false);

    //閉じる
    ns.Close();
    tcp.Close();
    SettxBoxReceive(GettxBoxReceive() + "クライアントとの接続を閉じました。¥r¥n");
    SettxBoxReceiveScrollEnd();
}

private void Btn_Send_Click(object sender, EventArgs e)
{
    if (tcp != null)
    {
        SendThread = new System.Threading.Thread(SendStart);
        SendThread.IsBackground = true;
        SendThread.Start();
    }

}

private void SendStart()
{
    //データを送信する
    System.Text.Encoding enc = System.Text.Encoding.UTF8;

    NetworkStream ns = null;

    //NetworkStreamを取得
    ns = tcp.GetStream();

    //タイムアウト設定
    ns.ReadTimeout = 10000;
    ns.WriteTimeout = 10000;
            
    //クライアントに送信する文字列を作成
    string sendMsg = txtBox_Send.Text;
    //文字列をByte型配列に変換
    byte[] sendBytes = enc.GetBytes(sendMsg + '¥r');
    //データを送信する
    ns.Write(sendBytes, 0, sendBytes.Length);

}

クライアント側の接続はシンプルです。

tcp = new System.Net.Sockets.TcpClient(strAdd, port);

System.Net.Sockets.TcpClientクラスにIPアドレスとポート番号を渡して、クラスをインスタンス化すれば良いです。相手側に接続できれば、受信テキストボックスに接続できたことを表示します。その後、スレッド処理をします。スレッド処理の中では、リスナー側から送られてくる文字列の処理をします。ここで、スレッド処理をしておかないと、他の動作ができないので、スレッド処理が必要です。スレッド処理については、また後程、記事を作成しようと思います。bStopFlgがfalseの間は、受信を続けます。接続を終了したい場合は、bStopFlgをfalseにする必要があるわけです。停止ボタンの動作に、bStopFlg=true;を追加すればよいですね。

また、スレッド処理をする際に注意する必要があることは、ダイアログの中のテキストボックスに文字を表示させてい時の処理です。ダイアログの画面は、受信スレッドとは、別のスレッドで動作しているので、そのまま、受信スレッドの中で、ダイアログのテキストボックスにはアクセスできません。そこで、SettxBoxReceive関数を作成しています。SettxBoxReceive関数では、コールバック関数を使用して、ダイアログにアクセスできるように関数を作成しております。こちらも後程、記事を作成しようと思います。

文字列の送信は、送信テキストボックスに文字を入力して、送信を押すと、リスナー側に文字列が送信されます。こちらも、スレッド処理で送信は行っています。タイムアウト設定をしているので、送信の場合は、スレッド処理をしなくてもよいです。

実際に文字を送受信してる画面は、リスナー側のTCP通信アプリケーションを作成した時に、画像を貼り付けたいと思います。

次回は、リスナー側のTCP通信アプリケーションを作成します。