今更ながらs.h.log: SocketでC#とProce55ingの通信の続き。学部の頃に徳田先生のネットワークプログラミングの授業で習ったような気がする事を勉強した。

実はTcpClient、TcpListener、Threadまわりを理解してこれを作るのに2ヶ月ぐらいかかった。

Archive(SrouceCode, exe / VisualStudio2005 C#2.0)

3つサンプルを作った。作った順に

1.SocketClient

普通にクライアント。指定したIPのportに接続する。テキストの送受信ができるウィンドウ付き。文字コードはUTF-8

2.SocketServer

普通のソケットサーバー。これ作ったときは、同じPortで複数のclientと接続できる事を知らなかった。SocketClientと1対1で対応する。

3.SocketBridge

SocketServerを改造して、複数clientとセッションをはれる様にした。コレはFlashのAS3から使えるようになったSocketにlistenメソッドが無いので、FlashとFlashを直接通信させる為のオスメス変換的ツールを目指して作った。(FlashMediaServer使えば良いんだけど)

clientから受信したデータを他の全てのclientに転送する様にしたので、ブリッジというよりハブかもしれない。

SocketClientとSocketServerを接続

Socket Client&Server



SocketServerを80番でlistenさせておいて、ブラウザでlocalhostにアクセスしたら反応した。

Socket Server&Firefox

Client複数をBridgeに接続してメッセージを配信してもらっているところ

Socket Client&Bridge

FlashからFlashにSocketBridge経由で動画をバイナリで送って再生してみた

Socket Bridge&FlashClient

大分勉強になった。

特に一番最後に作ったSocketBridgeはすっきり書けて200行ぐらいでできた。A4で印刷して3枚に収まる。。

FormSocketBridge.cs

usingSystem;

usingSystem.Collections.Generic;

usingSystem.ComponentModel;

usingSystem.Data;

usingSystem.Drawing;

usingSystem.Text;

usingSystem.Windows.Forms;

usingSystem.Net;//socket関連

usingSystem.Net.Sockets;

usingSystem.Threading;//thread関連

usingSystem.Collections;

namespaceSocketServerBridge

{

publicpartialclassFormSocketBridge:Form

{

privateSystem.Text.Encodingenc=System.Text.Encoding.UTF8;//文字コード

privateThreadthread;

privateBooleanthreadStopper;//スレッド停止フラグ

privateAutoResetEventthreadResetEvent;

privateTcpListenerlistener;

privateArrayListclients;

publicFormSocketBridge()

{

InitializeComponent();

clients=newArrayList();

}

#regionThread/Socke

///



///tcp,stream,threadの破棄

///


privatevoidconnectEnd()

{

if(thread==null)return;

threadStopper=true;//スレッド終了フラグ

threadResetEvent.WaitOne();//スレッド終了待ち

thread=null;//破棄

listener.Stop();

for(inti=0;i
{

try

{

((TcpClient)clients[i]).Close();

}

catch(Exceptionex)

{

debug(ex.Message);

}

}

}

///



///データ受信スレッド

///


privatevoidrecvThreadStart()

{

byte[]recvBytes;

intrecvSize=0;

threadStopper=false;

while(!threadStopper)

{

if(listener.Pending())//接続待ちがある時

{

TcpClienttcp=listener.AcceptTcpClient();

clients.Add(tcp);

trace(“Connected!”);

trace(“接続数:”+clients.Count);

}

else

{

for(inti=0;i
{

TcpClientclient=(TcpClient)clients[i];

if(!client.Connected)

{

clients.Remove(client);

trace(“DisConnected”);

trace(“接続数:”+clients.Count);

}

else

{

NetworkStreamns=client.GetStream();

if(ns.DataAvailable)//受信データがある時

{

recvBytes=newbyte[3750];

try

{

recvSize=ns.Read(recvBytes,0,recvBytes.Length);

}

catch(Exceptionex)

{

debug(ex.Message);

}

debug(“受信データ長:”+recvSize);

stringrecvMsg=enc.GetString(recvBytes);

debug(“受信データ:”+recvMsg);

ArrayListclients2=newArrayList();

for(intj=0;j
{

if(i!=j)clients2.Add(clients[j]);//送ってきた奴には送り返さない

}

broadcastToClients(recvBytes,clients2);

}

}

}

}

Thread.Sleep(10);

}

threadResetEvent.Set();//スレッド終了をWaitOne()に通知

}

privatevoidbroadcastToClients(byte[]bytes,ArrayListclients)

{

for(inti=0;i
{

TcpClienttcp=(TcpClient)clients[i];

NetworkStreamns=tcp.GetStream();

try

{

ns.Write(bytes,0,bytes.Length);

}

catch(Exceptionex)

{

debug(ex.Message);

}

}

}

#endregion

#regionUIEvent

privatevoidbuttonListen_Click(objectsender,EventArgse)

{

if(thread==null)

{

threadResetEvent=newAutoResetEvent(false);

//listen開始

listener=newTcpListener(IPAddress.Any,int.Parse(textBoxPort.Text));

listener.Start();

trace(“Listen!”);

buttonListen.Text=”DisConnect?”;

textBoxPort.Enabled=false;

thread=newThread(recvThreadStart);

thread.Start();//接続待ち

}

else

{

//listen,threadを止めてtcpsocketを閉じる

connectEnd();

buttonListen.Text=”Connect!”;

textBoxPort.Enabled=true;

trace(“DisConnected”);

}

}

privatevoidFormSocketBridge_FormClosed(objectsender,FormClosedEventArgse)

{

connectEnd();

}

#endregion

#regionUIMethod

///



///テキストボックスに表示する

///


///
publicvoidtrace(Stringmessage)

{

Console.WriteLine(message);

if(checkBoxDisplayLog.Checked)

{

try

{

this.Invoke((MethodInvoker)delegate()

{

textBoxLog.Text=textBoxLog.Text+”¥r¥n”+message;

});

}

catch(Exceptionex)

{

Console.WriteLine(ex.Message);

}

}

}

publicvoiddebug(Stringmessage)

{

#ifDEBUG

trace(message);

#endif

}

#endregion

}

}