LOSo講解
C#
Socket通訊
Socket通訊為使用Ethernet傳輸資訊的一種方式。運作的方式就如同電話撥接,透過設定插座的號碼,其他人就可透過這串號碼與其通話。而Socket的號碼就是IP Number加上TCP Port。
Socket的連線端可以分為主機端(Server)及客戶端(Client)。通常Server要先設定並連接上傳輸埠口,才能開始監聽是否有Client請求連接;而Client也一樣要連接上傳輸埠口,才能發送要求連線。而當通訊結束時,則會互相確認要中斷連線。
在C#程式裡,提供了Socket類別讓programmer可以更簡單的設計出可連線的應用程式。
Socket類別的宣告,如:(參閱連結)
Socket serverSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
常使用的方法有:
以下提供可執行Socket範例裡的Server及Client底層部分程式:
Server端程式:
public class AsServer
{
#region --公開事件--
public event EventHandler<EventArgsMsg> ServerGetMsgEvent; //Server獲得回訊的事件
public event EventHandler<EventArgsStateChange> ServerStateChangeEvent; //Server狀態改變的事件
#endregion --公開事件--
#region --欄位--
Socket serverSocket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);//地址型別,流,協議型別
//192.168.43.76 本機ip:127.0.0.1
Socket clientSocket = null; //宣告一個client的socket類別
IPEndPoint ipendpoint = null; //宣告一個通訊端位置
#endregion --欄位--
#region --屬性(傳出、接收)--
public string WriteInMsg { get; set; } //用於傳出訊息
public string MsgReceive { get; set; } //用於接收訊息
#endregion --屬性(傳出、接收)--
#region --建構式--
public AsServer(string ip, int port) //建構式,須帶入ip位置及通訊埠編號
{
IPAddress ipaddress = IPAddress.Parse(ip);
ipendpoint = new IPEndPoint(ipaddress, port);
}
#endregion --建構式--
#region --公開方法--
public void StartConnect() //開始連線的方法
{
if (ipendpoint != null)
{
try
{
serverSocket.Bind(ipendpoint);//繫結完成
StateChange(EConnect.Connected, string.Format("Server Connected"));
serverSocket.Listen(0);//處理連結佇列個數 為0則為不限制
ClientAccept();
}
catch
{
StateChange(EConnect.Disconnect, string.Format("Server has already been connect"));
}
}
}
public void Stop() //關閉socket的方法
{
if (serverSocket != null)
serverSocket.Close();
if (clientSocket != null)
clientSocket.Close();
StateChange(EConnect.Disconnect, "Disconnected!!");
}
#endregion --公開方法--
#region --私有方法--
private void ClientAccept() //此方法用於監聽Client的連線狀態
{
if (clientSocket != null) //排除錯誤問題
{
Stop();
StateChange(EConnect.Disconnect, string.Format("Client Socket Error"));
return;
}
Task.Factory.StartNew(() =>
{
clientSocket = serverSocket.Accept();//接收一個客戶端連結
StateChange(EConnect.Connected, string.Format("Client Connected"));
Task.Factory.StartNew(() => { MessageSender(); }); //建立新執行緒,以傳出訊息
Task.Factory.StartNew(() => { MessageReceiver(); }); //建立新執行緒,以接收訊息
});
}
private void MessageSender() //傳出訊息的方法
{
while (Configuration.ConnectState.Equals(EConnect.Connected))
{
while (Configuration.ConnectState.Equals(EConnect.Connected) && string.IsNullOrEmpty(WriteInMsg)) //當沒有要傳的資料時,在這打轉
{
Thread.Sleep(1);
}
byte[] date = System.Text.Encoding.UTF8.GetBytes(WriteInMsg);//將string加密,轉換成為bytes陣列
clientSocket.Send(date); //傳輸資料
WriteInMsg = string.Empty;
}
clientSocket.Close(); //關閉socket
}
private void MessageReceiver() //接收訊息的方法
{
while (Configuration.ConnectState.Equals(EConnect.Connected))
{
byte[] dateBuffer = new byte[1024]; //宣告接收資訊的空間
int count = clientSocket.Receive(dateBuffer); //存介面接收到資料
MsgReceive = System.Text.Encoding.UTF8.GetString(dateBuffer, 0, count); //解密為string格式
if (ServerGetMsgEvent != null)
{
EventArgsMsg msgArg = new EventArgsMsg();
msgArg.Message = MsgReceive;
ServerGetMsgEvent.Invoke(this, msgArg); //呼叫上層方法執行UI變更
}
MsgReceive = string.Empty;
}
clientSocket.Close(); //關閉socket
}
private void StateChange(EConnect state, string changeMsg = "") //當狀態改變,可呼叫上層變更UI的方法
{
Configuration.ConnectState = state;
if (ServerStateChangeEvent != null)
{
EventArgsStateChange arg = new EventArgsStateChange();
arg.StateMessage = changeMsg;
ServerStateChangeEvent.Invoke(this, arg);
}
}
#endregion --私有方法--
}
Client端程式:
public class AsClient
{
#region --公開事件--
public event EventHandler<EventArgsMsg> ClientGetMsgEvent; //Client獲得回訊的事件
public event EventHandler<EventArgsStateChange> ClientStateChangeEvent; //Client狀態改變的事件
#endregion --公開事件--
#region --欄位--
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //宣告一個client的socket類別
IPEndPoint ipendpoint = null; //宣告一個通訊端位置
#endregion --欄位--
#region --屬性(傳出、接收)--
public string WriteInMsg { get; set; } //用於傳出訊息
public string MsgReceive { get; set; } //用於接收訊息
#endregion --屬性(傳出、接收)--
#region --建構式--
public AsClient(string ip, int port) //建構式,須帶入ip位置及通訊埠編號
{
IPAddress ipaddress = IPAddress.Parse(ip);
ipendpoint = new IPEndPoint(ipaddress, port);
}
#endregion --建構式--
#region --公開方法--
public void StartConnect() //開始連線的方法
{
if (ipendpoint != null)
{
try //連接成功
{
clientSocket.Connect(ipendpoint);//繫結完成
StateChange(EConnect.Connected, string.Format("Client Connected"));
}
catch //連接失敗
{
StateChange(EConnect.Disconnect, string.Format("Connect Fail, please make sure that Server has been online"));
return;
}
Task.Factory.StartNew(() => { MessageSender(); }); //建立新執行緒,以傳出訊息
Task.Factory.StartNew(() => { MessageReceiver(); }); //建立新執行緒,以接收訊息
}
}
public void Stop() //關閉socket的方法
{
if (clientSocket != null)
clientSocket.Close();
StateChange(EConnect.Disconnect, "Disconnected!!");
}
#endregion --公開方法--
#region --私有方法--
private void MessageSender() //傳出訊息的方法
{
while (Configuration.ConnectState.Equals(EConnect.Connected))
{
while (Configuration.ConnectState.Equals(EConnect.Connected) && string.IsNullOrEmpty(WriteInMsg)) //當沒有要傳的資料時,在這打轉
{
Thread.Sleep(1);
}
byte[] date = System.Text.Encoding.UTF8.GetBytes(WriteInMsg); //將string加密,轉換成為bytes陣列
clientSocket.Send(date); //傳輸資料
WriteInMsg = string.Empty;
}
clientSocket.Close(); //關閉socket
}
private void MessageReceiver() //接收訊息的方法
{
while (Configuration.ConnectState.Equals(EConnect.Connected))
{
byte[] data = new byte[1024]; //宣告接收資訊的空間
int count = clientSocket.Receive(data); //存介面接收到資料
MsgReceive = System.Text.Encoding.UTF8.GetString(data, 0, count); //解密為string格式
if (ClientGetMsgEvent != null)
{
EventArgsMsg msgArg = new EventArgsMsg();
msgArg.Message = MsgReceive;
ClientGetMsgEvent.Invoke(this, msgArg); //呼叫上層方法執行UI變更
}
MsgReceive = string.Empty;
}
clientSocket.Close(); //關閉socket
}
private void StateChange(EConnect state, string changeMsg = "") //當狀態改變,可呼叫上層變更UI的方法
{
Configuration.ConnectState = state;
if (ClientStateChangeEvent != null)
{
EventArgsStateChange arg = new EventArgsStateChange();
arg.StateMessage = changeMsg;
ClientStateChangeEvent.Invoke(this, arg);
}
}
#endregion --私有方法--
}
執行結果:
物件導向編程(Object-oriented programming),縮寫OOP。顧名思義這種編程方式就是將程式封裝成一種物件,在使用上就會提高軟體的重用性、靈活性和擴充性。而通常一個物件(object)指的就是一個類別(class)的實例,類別可以提供公開的欄位(field)、屬性(attribute)、方法(method),使其他的程式碼可以呼叫使用,而我們的專案程式就是由物件們產生關聯而成的。
Mar 6, 2023委派 在我的LOSoMan的委派講解筆記裡,已經清楚地介紹了委派的用法及用途。 事件的宣告 通常我們講到事件會先提到委派的原因是因為事件的參數型別是從委派宣告出來的,舉個例子: public delegate void MyHandler(object sender, MyEventArgs arg); public event MyHandler MySomeWorks; 這裡可以明確的了解"MyHandler"是自創的委派型別,而"MySomeWorks"正是這個型別的事件。 其中"MyEventArgs"為一個繼承"EventArgs"的自訂類別,程式部分為:
Mar 6, 2023什麼是XML? XML為可延伸標記式語言,可用來傳送與攜帶資料資訊。那麼,XML跟HTML有什麼差別呢? XML著重在內容 HTML強調布局 而且,他們的格式寫法及用法也稍微不同: XML的元素名稱有分大小寫。HTML的標籤不分大小寫。 XML的元素一定都要有起始標籤和結尾標籤。而HTML的元素在某些情況下,可以不寫結尾標籤。
May 11, 2022委派的定義 Microsoft手冊上所說,委派(Delegate)為一種類型,只要有相同簽章和傳回型別的方法,都可與定義好的委派產生關聯。之後要使用時,先定義一個委派呼叫方法,然後帶入參數即可。 Microsoft手冊也說委派是可以安全封裝方法的類型。這句話對我而言,就好比委派一個可以裝載方法的容器,你可以把方法放入委派這個容器之中,自然也可以將方法從容器中卸載。而當我們要使用這個容器裡所有存放的方法,就只需要呼叫(Invoke)這個容器就行了。 宣告委派 話不多說,先來看看如何宣告一個委派: public delegate void NonDelegate(); public delegate void MyDelegate(int A);
May 11, 2022or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up