この知恵ノートを「知恵コレクション」に追加しました。
追加した知恵ノートはMy知恵袋の「知恵コレクション」ページで確認できます。
「知恵コレクション」に登録済みです。
再登録しました。
追加に失敗しました。
ノートに戻り、もう一度やり直してください。
すでに1,000件のノートが登録されています。
新しく追加したい場合は、My知恵袋の「知恵コレクション」ページで登録されているノートを削除してください。
追加できませんでした。
ノートは削除されました。
知恵コレに追加する:0人
「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 = "サーバー終了";
}
}
}
}
さいごに
コードの説明は、サンプルコード中に記してあります。
また、元ページの説明も参考にして下さい。
アドバイス(このノートのライターへのメッセージ)を送る
このノートはどうでしたか? いいと思ったことや、こうしたらもっとよくなるといったメッセージを送りましょう! ノートの内容やライターについて質問がある場合は、Q&Aから質問してみましょう
アドバイスを送るには、
Yahoo! JAPAN IDでのログインおよび
Yahoo!知恵袋の利用登録が必要です。
感想アドバイス履歴
-
現在アドバイスはありません
このノートに関するQ&A
このノートに関するQ&Aは、まだありません。
あなたにおすすめの知恵ノート
あなたにおすすめのQ&A
- C#でソケット通信をしたいんですが、 javaのSocketChannel#readのように受信データがなかったときに...
- このC#をCに直していただけませんか? using System; using System.Collections.Generic; using Sys...
- Cでソケット通信 Javaだとソケット通信とかは簡単ですが、やはり少し低級なC/C++は自分には難しいで...
- C#の質問です。 ネットで調べたり自分なりに考えてみたのですが、 サーバーからクライアントへデータ...
- .net TcpClientクラスについて 使用するTCPポートの宣言は以下のように行いますが、 this._tcpHost =...