- 有 server & client 兩端
- server 只有一個,而 client 有可能會多個
- server 可設定監聽(listen)的 port number
以下直接用範例來說明囉!
(其中 SocketServer 跟新的 client 連線後,會交給 ClientRequestHandler 處理)
SocketServer.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.ComponentModel;
namespace SocketConn
{
class SocketServer
{
#region private property
/// /// socket server TCP port number
/// private int _PortNumber;
/// /// TCP Listener
/// private TcpListener _Listener;
/// /// 用來處理 Listener 工作的執行緒
/// private BackgroundWorker _bgwServer = new BackgroundWorker();
/// /// socker client 識別編號
/// private int _ClientNo = 0;
#endregion
#region static public property
/// /// 工作進行中產生之訊息
/// public static List sMessages = new List();
#endregion
#region constructor
/// /// constructor
/// ///
socket server TCP port number
public SocketServer(int inPortNumber)
{
this._PortNumber = inPortNumber;
//委派事件
_bgwServer.DoWork += new DoWorkEventHandler(_bgwServer_DoWork);
}
#endregion
#region public method
/// /// 開始監聽
/// public void Start()
{
if (!_bgwServer.IsBusy)
_bgwServer.RunWorkerAsync();
}
#endregion
#region BackgroundWorker
///
/// 處理 Listener 工作
/// ///
///
private void _bgwServer_DoWork(object sender, DoWorkEventArgs e)
{
try
{
//若 TCP Listner 正在工作,則停止
if (_Listener != null)
_Listener.Stop();
//初始化 TCPListener
_Listener = new TcpListener(IPAddress.Any, _PortNumber);
//啟動 listener
_Listener.Start();
sMessages.Add(" >> " + "Server Started");
//========== 持續接受監聽 socket client 的連線 ========== (start)
while (true)
{
//監聽到來自 socket client 的連線要求
TcpClient socket4Client = _Listener.AcceptTcpClient();
//累加 socket client 識別編號
_ClientNo++;
sMessages.Add(" >> " + "Client Request No:" + Convert.ToString(_ClientNo) + " started!");
//產生 BackgroundWorker 負責處理每一個 Socket Client 的要求
ClientRequestHandler handler = new ClientRequestHandler(_ClientNo, socket4Client);
handler.DoCommunicate();
}
//========== 持續接受監聽 socket client 的連線 ========== (end)
}
catch (Exception exp)
{
sMessages.Add(exp.ToString());
}
}
#endregion
}
}
ClientRequestHandler.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.ComponentModel;
namespace SocketConn
{
class ClientRequestHandler
{
#region private property
/// /// socket client 識別號碼
/// private int _ClientNo;
/// /// socket client reuqest
/// private TcpClient _TcpClient;
#endregion
#region constructor
/// /// constructor
/// ///
socket client 識別號碼
///
socket client reuqest
public ClientRequestHandler(int inClientNo, TcpClient inTcpClient)
{
this._ClientNo = inClientNo;
this._TcpClient = inTcpClient;
}
#endregion
#region public method
/// /// server & client 間相互進行通訊
/// public void DoCommunicate()
{
//產生 BackgroundWorker 負責處理每一個 socket client 的 reuqest
BackgroundWorker bgwSocket = new BackgroundWorker();
bgwSocket.DoWork += new DoWorkEventHandler(bgwSocket_DoWork);
bgwSocket.RunWorkerAsync();
}
#endregion
#region BackgroundWorker
/// /// 處理 socket client request
/// private void bgwSocket_DoWork(object sender, DoWorkEventArgs e)
{
//server & client 已經連線完成
while (_TcpClient.Connected)
{
//取得網路串流物件,取得來自 socket client 的訊息
NetworkStream netStream = _TcpClient.GetStream();
byte[] readBuffer = new byte[1024];
int count = 0;
if ((count = netStream.Read(readBuffer, 0, readBuffer.Length)) != 0)
{
string clientRequest = Encoding.UTF8.GetString(readBuffer, 0, count);
SocketServer.sMessages.Add(" >> " + "From client(" + _ClientNo + ") =>" + clientRequest);
//正確取得 client requst,再回傳給 client
string serverResponse = "Server to clinet(" + _ClientNo + ") => message: " + clientRequest;
byte[] sendBytes = Encoding.UTF8.GetBytes(serverResponse);
netStream.Write(sendBytes, 0, sendBytes.Length);
netStream.Flush();
SocketServer.sMessages.Add(" >> " + serverResponse);
}
}
}
#endregion
}
}
SocketClient.cs
using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
namespace SocketConn
{
class SocketClient
{
#region private property
/// /// 遠端 socket server IP 位址
/// private string _RemoteIpAddress;
/// /// 遠端 socket server 所監聽的 port number
/// private int _RemotePortNumber;
/// /// socket client 物件(連接遠端 socket server 用)
/// private TcpClient _TcpClient;
#endregion
#region public static property
public static List sMessages = new List();
#endregion
#region constructor
/// /// constructor
/// ///
遠端 socket server IP 位址
///
遠端 socket server 所監聽的 port number
public SocketClient(string inRemoteIpAddr, int inRemotePortNum)
{
this._RemoteIpAddress = inRemoteIpAddr;
this._RemotePortNumber = inRemotePortNum;
}
#endregion
#region public method
/// /// 連線至 socket server
/// public void Connect()
{
//初始化 socket client
_TcpClient = new TcpClient();
_TcpClient.Connect(_RemoteIpAddress, _RemotePortNumber);
sMessages.Add("Client Socket Program - Server Connected ...");
}
/// /// 傳送訊息至 socker server
/// ///
訊息
/// socker server 回傳結果
public string Send(string inMessage)
{
try
{
//取得用來傳送訊息至 socket server 的 stream 物件
NetworkStream serverStream = _TcpClient.GetStream();
//將資料轉為 byte[]
byte[] outStream = System.Text.Encoding.UTF8.GetBytes(inMessage);
//將資料寫入 stream object (表示傳送資料至 socket server)
serverStream.Write(outStream, 0, outStream.Length);
serverStream.Flush();
//讀取 socket server 回傳值並轉為 string
byte[] inStream = new byte[10025];
serverStream.Read(inStream, 0, (int)_TcpClient.ReceiveBufferSize);
string returndata = System.Text.Encoding.UTF8.GetString(inStream);
sMessages.Add("Data from Server : " + returndata);
return returndata;
}
catch (Exception exp)
{
sMessages.Add(exp.ToString());
return exp.ToString();
}
}
#endregion
}
}
public static List sMessages = new List();
回覆刪除public static List sMessages = new List();
回覆刪除請問MAIN()裡需要先放哪些函式??~.~
回覆刪除作者已經移除這則留言。
回覆刪除public static List sMessages = new List();
回覆刪除型別被吃掉了
參照
http://dreamtails.pixnet.net/blog/post/23947420-c%23-%E8%A3%A1-list%E7%94%A8%E6%B3%95%EF%BC%8C%E6%9C%89%E9%BB%9E%E5%83%8F%E6%98%AF%E4%B8%8D%E7%94%A8%E5%AE%A3%E5%91%8A%E9%95%B7%E5%BA%A6%E7%9A%84%E9%99%A3%E5%88%97(