C#言語(4)-TCP通信(リスナー編)

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

今回は、リスナー側のTCP通信アプリケーションの作成です。作成するダイアログは下記のようになります。あまり、クライアント側のTCP通信アプリケーションと違いはありませんね・・・。

ソースコードは以下の通りです。※クライアントからの接続待ち、接続、データの送受信の部分を抜粋です。

private void Btn_Start_Click(object sender, EventArgs e)
{

    if (listener == null)
    {
        bStopFlg = false;

        clientList = new List();

        //----------------------------------------------
        // スレッド処理
        //----------------------------------------------
        ListenThread = new System.Threading.Thread(new System.Threading.ThreadStart(ListenStart));
        ListenThread.IsBackground = true;
        ListenThread.Start();
    }
    else
    {
        MessageBox.Show("接続待ちです。");
    }

}

private void ListenStart()
{
    //IPアドレスの設定、ポート番号の設定、TcpListener作成
    System.Net.IPAddress ipAdd = System.Net.IPAddress.Parse(GettxBoxIP());
    listener = new System.Net.Sockets.TcpListener(ipAdd, int.Parse(GettxBoxPort()));

    //Listenを開始する
    listener.Start();
    SettxBoxReceive(GettxBoxReceive() + "Listenを開始しました(" + ((System.Net.IPEndPoint)listener.LocalEndpoint).Address + ":" + ((System.Net.IPEndPoint)listener.LocalEndpoint).Port + ")。¥r¥n");
    SettxBoxReceiveScrollEnd();

    //接続要求があったら受け入れる
    do
    {
        System.Net.Sockets.TcpClient client = null;
        try
        {
            client = listener.AcceptTcpClient();
        }
        catch (SocketException e)
        {
            SettxBoxReceive(GettxBoxReceive() + "Listenerを閉じました。¥r¥n");
            SettxBoxReceiveScrollEnd();
            return;
        }

        SettxBoxReceive(GettxBoxReceive() + "クライアント(" + ((System.Net.IPEndPoint)listener.LocalEndpoint).Address + ")" + ((System.Net.IPEndPoint)listener.LocalEndpoint).Port + "と接続しました。¥r¥n");
        SettxBoxReceiveScrollEnd();

        clientList.Add(client);

        //----------------------------------------------
        // スレッド処理
        //----------------------------------------------
        ReceiveThread = new System.Threading.Thread(ReceiveStart);
        ReceiveThread.IsBackground = true;
        ReceiveThread.Start(client);
    } while (bStopFlg == false);

    //リスナを閉じる
    listener.Stop();
    listener = null;
    Console.WriteLine("Listenerを閉じました。");
    SettxBoxReceive(GettxBoxReceive() + "Listenerを閉じました。¥r¥n");
    SettxBoxReceiveScrollEnd();
}

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

    NetworkStream ns = null;

    TcpClient client = (TcpClient)iclient;

    //NetworkStreamを取得
    ns = client.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();
    client.Close();
    SettxBoxReceive(GettxBoxReceive() + "クライアントとの接続を閉じました。¥r¥n");
    SettxBoxReceiveScrollEnd();
}


private void Btn_Stop_Click(object sender, EventArgs e)
{
    bStopFlg = true;
}

private void Btn_Send_Click(object sender, EventArgs e)
{

    if (clientList.Count != 0)
    {
        //----------------------------------------------
        // スレッド処理
        //----------------------------------------------
        SendThread = new System.Threading.Thread(new System.Threading.ThreadStart(SendStart));
        SendThread.IsBackground = true;
        SendThread.Start();
    }
            
}

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

    //Console.WriteLine();
    foreach (TcpClient client in clientList)
    {
        NetworkStream ns = null;

        //NetworkStreamを取得
        ns = client.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);
    }
}

リスナー側は、クライアント側の接続を待ちます。まずは、IPアドレスとポートを指定して、TcpListenerクラスをインスタンス化します。

listener = new System.Net.Sockets.TcpListener(ipAdd, int.Parse(GettxBoxPort()));

次に、TcpListenerのStartメソッドで接続待ちを開始します。

client = listener.AcceptTcpClient();

接続待ちをしている間、他の処理を受け付けなくなってしまうので、スレッド処理をしておいた方がよいです。クライアント側から接続があると、リスナーはクライアント情報を取得します。

client = listener.AcceptTcpClient();

このクライアント情報を使用して、データの送受信をします。データの送受信処理は、クライアント側の処理とほぼほぼ同じです。

クライアント側

サーバー側