Skip to content

Instantly share code, notes, and snippets.

@noqisofon
Created November 15, 2010 08:40
Show Gist options
  • Save noqisofon/700172 to your computer and use it in GitHub Desktop.
Save noqisofon/700172 to your computer and use it in GitHub Desktop.
TcpListener クラスのデモっぽい。
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;
namespace sample.demo.tcplistener.app.widgets {
/// <summary>
///
/// </summary>
public partial class TCPListenerDemoForm : Form {
/// <summary>
///
/// </summary>
public TCPListenerDemoForm() {
InitializeComponent();
}
/// <summary>
/// tbResult.Text に result を付け足します。
/// </summary>
/// <remarks>
/// 呼び出し側が別スレッドで動いている場合、ウィジェット(コントロール)にアクセスすることはできないので、
/// Invoke メソッドを使う。
/// そのためのメソッド。
/// </remarks>
/// <param name="result"></param>
private void result_append_to_textbox(string result) {
StringBuilder text_builder = new StringBuilder( tbResult.Text );
text_builder.AppendLine( result );
tbResult.Text = text_builder.ToString();
}
/// <summary>
///
/// </summary>
private void beginBackgroundWorker() {
IPAddress ip_address;
int port = int.Parse( tbPortNumber.Text );
if ( tbIpAddress.Text.Length == 0 ) {
IPHostEntry host = Dns.GetHostEntry( Dns.GetHostName() );
Stack<IPAddress> address_stack = new Stack<IPAddress>( host.AddressList );
// ローカル IP アドレスで聞き耳をたてます。
ip_address = address_stack.Pop();
} else
ip_address = IPAddress.Parse( tbIpAddress.Text );
IPEndPoint local_endpoint = new IPEndPoint( ip_address, port );
backgroundWorker.RunWorkerAsync( local_endpoint );
}
/// <summary>
/// フォームが読み込まれたときに呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="ergs"></param>
private void TCPListenerDemoForm_Load(object sender, EventArgs ergs) {
}
/// <summary>
/// フォームが最初に表示されたときに呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="ergs"></param>
private void TCPListenerDemoForm_Shown(object sender, EventArgs ergs) {
beginBackgroundWorker();
}
/// <summary>
/// このフォームが閉じられる前に呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="fcergs"></param>
private void TCPListenerDemoForm_FormClosing(object sender, FormClosingEventArgs fcergs) {
if ( fcergs.CloseReason == CloseReason.UserClosing ) {
fcergs.Cancel = true;
this.Hide();
}
}
/// <summary>
/// 「開始」ボタンがクリックされたときに呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="ergs"></param>
private void btnWorkStart_Click(object sender, EventArgs ergs) {
if ( !backgroundWorker.IsBusy ) {
beginBackgroundWorker();
}
btnWorkStart.Enabled = false;
btnWorkStop.Enabled = true;
}
/// <summary>
/// 「停止」ボタンがクリックされたときに呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="ergs"></param>
private void btnWorkStop_Click(object sender, EventArgs ergs) {
if ( backgroundWorker.IsBusy ) {
backgroundWorker.CancelAsync();
}
}
/// <summary>
/// タスクトレイアイコンをダブルクリックしたときに呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="ergs"></param>
private void tcpListenerNotifyIcon_DoubleClick(object sender, EventArgs ergs) {
this.Show();
if ( this.WindowState == FormWindowState.Minimized ) {
this.WindowState = FormWindowState.Normal;
}
this.Activate();
}
/// <summary>
/// タスクトレイアイコンのコンテキストメニュー「終了」をクリックしたときに呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="ergs"></param>
private void tsmiQuit_Click(object sender, EventArgs ergs) {
backgroundWorker.CancelAsync();
Application.Exit();
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="dwergs"></param>
private void backgroundWorker_DoWork(object sender, DoWorkEventArgs dwergs) {
try {
int report = 0;
IPEndPoint local_endpoint = dwergs.Argument as IPEndPoint;
backgroundWorker.ReportProgress( report++, "TcpListener オブジェクトを作成します。" );
this.server_ = new TcpListener( local_endpoint );
backgroundWorker.ReportProgress( report++, string.Format( "受信要求の待機を開始します。{0}", local_endpoint ) );
this.server_.Start();
byte[] received_bytes = new byte[256];
string received_text = null;
backgroundWorker.ReportProgress( report++, "ループを開始します。" );
while ( true ) {
received_text = null;
// 接続要求があれば接続を受け入れ、なければ 100 ミリ秒寝ます。
if ( this.server_.Pending() ) {
backgroundWorker.ReportProgress( report++, "接続要求がありました。" );
TcpClient client = this.server_.AcceptTcpClient();
backgroundWorker.ReportProgress( report++, "接続しました。" );
NetworkStream stream = client.GetStream();
int amount_of_bytes_read = 0;
while ( ( amount_of_bytes_read = stream.Read( received_bytes, 0, received_bytes.Length ) ) != 0 ) {
received_text = Encoding.UTF8.GetString( received_bytes, 0, amount_of_bytes_read );
backgroundWorker.ReportProgress( report++, received_text );
string response_text = "<response><result status=\"200\">OK</result></response>";
byte[] response_bytes = Encoding.UTF8.GetBytes( response_text );
stream.Write( response_bytes, 0, response_bytes.Length );
}
backgroundWorker.ReportProgress( report++, "接続を閉じています。" );
stream.Close();
client.Close();
} else
Thread.Sleep( 100 );
if ( backgroundWorker.CancellationPending ) {
dwergs.Cancel = true;
return;
}
}
} catch ( SocketException se ) {
dwergs.Result = se;
dwergs.Cancel = true;
return;
}
}
/// <summary>
/// ReportProgress メソッドが呼び出されたときに呼び出されます。
/// </summary>
/// <param name="sender"></param>
/// <param name="pcergs"></param>
private void backgroundWorker_ProgressChanged(object sender, ProgressChangedEventArgs pcergs) {
if ( pcergs.ProgressPercentage >= 0 )
result_append_to_textbox( string.Format( "{0}. {1}", pcergs.ProgressPercentage, pcergs.UserState ) );
else {
if ( pcergs.UserState is SocketException ) {
SocketException se = pcergs.UserState as SocketException;
result_append_to_textbox( string.Format( "{0}: {1}", se.NativeErrorCode, se.Message ) );
result_append_to_textbox( se.StackTrace );
} else
result_append_to_textbox( pcergs.UserState.ToString() );
}
}
/// <summary>
///
/// </summary>
/// <param name="sender"></param>
/// <param name="wrcergs"></param>
private void backgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs wrcergs) {
if ( wrcergs.Cancelled )
result_append_to_textbox( "キャンセルされました。" );
else
result_append_to_textbox( "終了しました。" );
btnWorkStart.Enabled = true;
btnWorkStop.Enabled = false;
this.server_.Stop();
}
/// <summary>
///
/// </summary>
TcpListener server_ = null;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment