ここから本文です

この知恵ノートを「知恵コレクション」に追加しました。

追加した知恵ノートはMy知恵袋の「知恵コレクション」ページで確認できます。

知恵コレクション」に登録済みです。

再登録しました。

追加に失敗しました。

ノートに戻り、もう一度やり直してください。

すでに1,000件のノートが登録されています。

新しく追加したい場合は、My知恵袋の「知恵コレクション」ページで登録されているノートを削除してください。

追加できませんでした。

ノートは削除されました。

「C#でソケット通信のノンブロッキング通信サーバーの作成 第2段(TcpListener + TcpClient)」のコード

ライターabiko_tetuさん(最終更新日時:2012/11/5)投稿日:2012/1/23 アドバイス受付中!

  • ナイス!:

    17

  • 閲覧数:1755

印刷用のページを表示する

*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

「C# で ソケット通信の ノンブロッキング通信サーバーの作成 第2段(TcpListener + TcpClient)」のコード


*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*

.






元のページ


元ページ「C# で ソケット通信の 電文処理用スレッド対応 - 同期通信サーバーの作成 第2段(TcpListener + TcpClient)」
http://note.chiebukuro.yahoo.co.jp/detail/n1660


記述量上限の制限で、ページを分けて記述しています。












はじめに


元ページの「C# で ソケット通信の ノンブロッキング通信サーバーの作成 第2段(TcpListener + TcpClient)」におけるコードをここに記述します。






コード







using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace ServerByAsynchronousTcpListener
{


    // ************************************************
    // ************************************************
    // ソケット通信の ノンブロッキング通信サーバー
    //
    // [特徴]
    // 通信クラス ---> TcpListener + TcpClient
    //  1) サーバーの主制御: TcpListenerクラス
    //  2) クライアントへの送受信: TcpClientクラス
    // 通信方式 ---> 同期式
    // 電文処理用スレッドの対応/未対応 ---> スレッド化に対応
    //       (電文処理部を複数のスレッドとして起動することを可能
    //         にして、複数クライアントの同時接続に対応する)
    // 電文処理用スレッドの作成方法 -->ソケット関連機能で用意され
    //                                 ているスレッド機能を使用

    // ************************************************
    // ************************************************

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();

            // スレッドからテキストボックスをアクセスすることを指定
            Control.CheckForIllegalCrossThreadCalls = false;
        }

 

        // ************************************************
        // メンバー変数
        // ************************************************
        private System.Net.Sockets.TcpListener server;  // リスナー(接続待ちや受信等を行なうオブジェクト)
        private System.Threading.Thread ListeningCallbackThread;   // 接続待ちスレッド
        private volatile bool SLTAlive;  // 接続待ちスレッド終了指示フラグ(volatile が指定されていることに注意)

        // 待機中のスレッドを管理するオブジェクト
        public static System.Threading.ManualResetEvent AllDone = new System.Threading.ManualResetEvent(false);

 

        // ************************************************
        // フォーム起動時イベント
        // ************************************************
        private void Form1_Load(object sender, EventArgs e)
        {

            this.Text = "サーバー(TcpListener + TcpClient)";   // フォームのタイトル名
            button1.Text = "サーバー開始"; // 開始ボタンの表示文字
            button2.Text = "サーバー終了"; // 終了ボタンの表示文字
            label1.Text = "";       // 状態表示用ラベルを初期化

            // スレッド終了指示フラグを未終了に初期化
            SLTAlive = false;

        }

 

        // ************************************************
        // フォーム閉鎖時イベント
        // ************************************************
        private void Form1_FormClosed(object sender, FormClosedEventArgs e)
        {
            // サーバアプリを終了するにもかかわらず、接続待ちスレッドを終了していない場合の処理
            if (SLTAlive)
            {

                // スレッド終了指示フラグを終了に設定
                SLTAlive = false;

                // 接続要求受け入れの終了
                server.Stop();

                // 念のためスレッドをnull設定
                ListeningCallbackThread = null;

            }


        }

 

        // ************************************************
        // 接続待ち開始ボタンのクリックイベント
        // ************************************************
        private void button1_Click(object sender, EventArgs e)
        {

            if (!SLTAlive)  // まだ接続待ちスレッドを生成していない場合
            {

                // リスナー(接続要求受け入れ待機)を生成
                server = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Parse("127.0.0.1"), 9000);
                // *** server = new System.Net.Sockets.TcpListener(System.Net.IPAddress.Any, 9000);

                // 接続要求受け入れ開始
                server.Start();

                // 接続待ち用スレッドを作成
                ListeningCallbackThread = new System.Threading.Thread(ListeningCallback);

                // 接続待ち用スレッドを開始
                ListeningCallbackThread.Start();

                // スレッド終了指示フラグを未終了に設定
                SLTAlive = true;

            }

        }

 

        // ************************************************
        // 接続待ち終了ボタンのクリックイベント
        // ************************************************
        private void button2_Click(object sender, EventArgs e)
        {

            if (SLTAlive)  // 接続待ちスレッドが作成されていて使える場合
            {

                if (server != null)
                {
                    // 接続要求受け入れの終了
                    server.Stop();
                }

                // スレッド終了指示フラグを終了に設定
                SLTAlive = false;

                label1.Text = "サーバー終了";

            }

        }

 

        // ************************************************
        // 送受信電文処理スレッド用メソッド
        //  --- 受信された電文に対して、具体的な処理を行なうメソッドです。このサ
        //      ンプルでは、受信電文をテキストボックスに表示し、また、クライアン
        //      トへ返信を返す処理としています。
        //      なお、本メソッド(電文処理部)は、複数のクライアントからの接続に対
        //      応しています。すなわち、受信があるたびにスレッドが起動し、本メソ
        //      ッドが実行されます。
        // 第1引数: TcpListenerクラスが受信処理を行なった後の処理結果
        // ************************************************
        public void CommunicationCallback(IAsyncResult ar)
        {

            // AllDoneをシグナル状態にする。
            // すなわち、接続待ちスレッドのロックを解除して、接続待ちスレッドの実行再開の許可をする。
            AllDone.Set();

            if (SLTAlive)  // 接続待ちスレッドが作成されていて使える場合
            {
                // クライアントからの受信接続要求を処理するリスナー(接続待ち用オブジェクト)を取得
                System.Net.Sockets.TcpListener listener = (System.Net.Sockets.TcpListener)ar.AsyncState;

                // クライアントへの送受信電文操作用のソケット
                System.Net.Sockets.TcpClient ClientSocket = listener.EndAcceptTcpClient(ar);

                // 通信ストリームの取得
                System.Net.Sockets.NetworkStream stream = ClientSocket.GetStream();

                try
                {

                    // クライアントからの電文の受信
                    byte[] ReceiveData = new byte[2000];
                    int DataLength = stream.Read(ReceiveData, 0, ReceiveData.Length);   // 電文の列長
                    string str = System.Text.Encoding.Unicode.GetString(ReceiveData, 0, DataLength);
                    textBox1.Text = str;    // 受信データ

                    // 返信電文をクライアントへ送信
                    byte[] SendBuffer = System.Text.Encoding.Unicode.GetBytes("本サーバーの御利用ありがとう御座います。");
                    stream.Write(SendBuffer, 0, SendBuffer.Length);
                    stream.Flush(); // フラッシュ(強制書き出し)

                }
                catch (Exception ex)
                {
                }


                // TCPクライアントをクローズ
                ClientSocket.Close();

            }


        }

 

        // ************************************************
        // 接続待ちスレッド用メソッド
        //  --- クライアントからの受信受け付けを行なうメソッドです。なお、受信受
        //      け付けを常に行なうため、無限ループで受け付け処理を行っています。
        //      無限ループは、処理を占有して、本サーバープログラム自体の動作に影
        //      響しますので、本メソッドは、スレッドとして起動します。
        // ************************************************
        private void ListeningCallback()
        {

            label1.Text = "サーバー開始";

            try
            {

                // 受信の受付を行なうための無限ループ
                while (SLTAlive)    // スレッド終了指示フラグでの終了指示がある場合はループ終了
                {

                    // AllDoneを非シグナル状態にする
                    // すなわち、スレッドの実行指示の状態をリセットして戻す。
                    AllDone.Reset();


                    // スレッドを起動し、送受信電文処理スレッド用メソッドを実行します。
                    server.BeginAcceptTcpClient(
                        new AsyncCallback(CommunicationCallback),
                        server);

                    // AllDoneがシグナル状態になるまでスレッドをブロック。
                    // すなわち、送受信電文処理用スレッドから、実行開始の指示が出るまで待機する。
                    AllDone.WaitOne();

                }
            }
            catch (Exception ex)
            {
                label1.Text = "サーバー終了";
            }
        }


    }


}












さいごに


コードの説明は、サンプルコード中に記してあります。
また、元ページの説明も参考にして下さい。



Yahoo!ブックマークに登録

アドバイス(このノートのライターへのメッセージ)を送る

このノートはどうでしたか?  いいと思ったことや、こうしたらもっとよくなるといったメッセージを送りましょう! ノートの内容やライターについて質問がある場合は、Q&Aから質問してみましょう

アドバイスを送るには、
Yahoo! JAPAN IDでのログインおよび
Yahoo!知恵袋の利用登録が必要です。

利用登録ナビへ

感想アドバイス履歴

  • 現在アドバイスはありません

このノートに関するQ&A

このノートに関するQ&Aは、まだありません。

このノートについて質問する

このノートについてライターの方に質問できます。

※ライターの方から必ず回答をいただけるとは限りません

※別ウィンドウで開きます

PR

PR

この知恵ノートのライター

グレード

グレード知恵ノートのグレード:2-3

知恵袋マスター

abiko_tetuさん男性

ピックアップ

アクション映画の銃撃戦はウソ...
アクション映画と言えば派手な銃撃戦が売りの一つですよね。...
流しの排水口のヌメリを簡単に...
 流しの排水口はすぐ汚れが付着するので、掃除をまめにしない...
☆ドラマの舞台へようこそ!~定...
はじめに<※2012年10月期ドラマ名を追記しました。> ドラマ...

こんなノートがほしい! リクエストする

最大文字数100文字入力できます

リクエストが送信されました。

いただいたリクエストは、Yahoo!知恵袋スタッフが確認のうえ、ライターの方向けに書いていただきたいテーマとして掲出いたします。

続けてリクエストする

リクエストされている知恵ノートを書く

いま求められているのは、こんな「知恵」。お題をクリックして投稿してみましょう!

知恵ノートを書いてみませんか?知恵ノートの書き方はこちら

知恵ノートとは?

役立つ知恵情報は、Yahoo!知恵袋公式Twitter@yahoochiebukuroをフォロー
本文はここまでです このページの先頭へ

お得情報

太陽のマテ茶プレゼント中
香ばしく、スッキリした後味
すき焼き食べたらマテ!

その他のキャンペーン