【Unity】Socket 同步與非同步
阿新 • • 發佈:2019-02-16
同步Socket 與 非同步 Socket:
1.同步就是阻塞的,比如 接受資料 如果沒有迴應 就一直等待。
2.非同步就是不用等待;
同步Socket
<span style="font-size:24px;">using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Text; using System.Net; using System.Net.Sockets; using System.Threading; //多執行緒 namespace MySocket { class Program { //用於連線 public static Socket connSocket; //用於請求 public static Socket ComdSocket; public static byte[] buf = new byte[1024]; static void Main (string[] args) { //開啟一個新的執行緒當客戶端 Thread client = new Thread (InitClient); client.Start ();//開啟 InitServer (); Console.Read (); } public static void InitServer () { //操作都放到try和catch中,以捕捉異常 connSocket = new Socket (AddressFhamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //例項化一個終端 IPEndPoint endPoint = new IPEndPoint (IPAddress.Parse ("127.0.0.1"), 3535); //佔用一個房間 connSocket.Bind (endPoint); //用於監聽,可以接受10個人 connSocket.Listen (10); //接受客戶端物件, 重點:阻塞方法(block) ComdSocket = connSocket.Accept (); Console.WriteLine ("有客戶端連線了,終端為" + ComdSocket.RemoteEndPoint); while (true) { //接受資料,阻塞方法(block) int len = ComdSocket.Receive (buf); string msg = Encoding.UTF8.GetString (buf, 0, len); Console.WriteLine ("收到新的訊息:" + msg); } } public static void InitClient () { // Thread.Sleep (3000);//休眠1000毫秒,保證伺服器開啟之後才能連線 connSocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //例項化一個終端 IPEndPoint endPoint = new IPEndPoint (IPAddress.Parse ("127.0.0.1"), 3535); //連線伺服器 connSocket.Connect (endPoint); Console.WriteLine (connSocket.Connected); if (connSocket.Connected) { while (true) { //客戶端傳送資料給伺服器 Console.WriteLine ("client input:"); string msg = Console.ReadLine (); //講一個字串轉換成byte[] buf = Encoding.UTF8.GetBytes (msg); //傳送資料 connSocket.Send (buf); } } } } }</span>
非同步Socket
using UnityEngine; using System.Collections; //關於網路 using System.Net; //關於套接字 using System.Net.Sockets; //關於文字 using System.Text; //宣告一個委託 public delegate void ldyReceiveCallBack (string content); public class LdySocket { #region 伺服器端 //宣告一個伺服器端的套接字 Socket serverSocket; //宣告一個委託物件 ldyReceiveCallBack serverCallBake; //生成一個位元快取 byte[] serverBuffer = new byte[1024]; //初始化伺服器 public void InitServer (ldyReceiveCallBack rcb) { //傳入委託物件 serverCallBake = rcb; //初始化伺服器端的套接字 serverSocket = new Socket (AddressFamily.InterNetwork/*IPV4*/, SocketType.Stream/*雙向讀寫流(服務端可以發給客戶 客戶也可以發服務)*/, ProtocolType.Tcp/*TCP協議*/); //例項一個網路端點 傳入地址和埠 IPEndPoint serverEP = new IPEndPoint (IPAddress.Any, 23456); //繫結網路端點 serverSocket.Bind (serverEP); //設定最大監聽數量 serverSocket.Listen (10); //非同步接受客戶端的連線(CallBack) serverSocket.BeginAccept (new System.AsyncCallback (ServerAccept), serverSocket); //傳送一個訊息 表示伺服器已經建立 serverCallBake ("Server Has Init"); } //伺服器接受 void ServerAccept (System.IAsyncResult ar) { //接受結果狀態 serverSocket = ar.AsyncState as Socket; //接收結果 Socket workingSocket = serverSocket.EndAccept (ar); workingSocket.BeginReceive (serverBuffer/*訊息快取*/, 0/*接受訊息的偏移量 就是從第幾個開始*/, this.serverBuffer.Length/*設定接受位元組數*/, SocketFlags.None/*Socket標誌位*/, new System.AsyncCallback (ServerReceive)/*接受回撥*/, workingSocket/*最後的狀態*/); //繼續接受客戶端的請求 workingSocket.BeginAccept (new System.AsyncCallback (ServerAccept), workingSocket); } void ServerReceive (System.IAsyncResult ar) { //獲取正在工作的Socket物件(用來接受資料的 ) Socket workingSocket = ar.AsyncState as Socket; //接受到得資料位元組 int byteCount = 0; //接收到的資料字串 string content = ""; try { byteCount = workingSocket.EndReceive (ar); } catch (SocketException ex) { //如果接受失敗 返回詳細異常 serverCallBake (ex.ToString ()); } if (byteCount > 0) { //轉換byte陣列為字串(支援中文) content = UTF8Encoding.UTF8.GetString (serverBuffer); } //傳送接收到的訊息 serverCallBake (content); //繼續接受訊息 workingSocket.BeginReceive (serverBuffer/*訊息快取*/, 0/*接受訊息的偏移量 就是從第幾個開始*/, this.serverBuffer.Length/*設定接受位元組數*/, SocketFlags.None/*Socket標誌位*/, new System.AsyncCallback (ServerReceive)/*接受回撥*/, workingSocket/*最後的狀態*/); } #endregion #region //宣告客戶端的套接字 Socket clientSocket; //宣告客戶端的委託物件 ldyReceiveCallBack clientReceiveCallBack; //宣告客戶端的快取1KB byte[] clientBuffer = new byte[1024]; //1.ip地址 2.埠3.委託物件 public void InitClient (string ip, int port, ldyReceiveCallBack rcb) { //接受委託物件 clientReceiveCallBack = rcb; //例項客戶端的Socket 引數(IPV4 ,雙向讀寫流,TCP協議) clientSocket = new Socket (AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //例項化一個客戶端的網路端點 IPAddress.Parse (ip):將IP地址字串轉換為Ip地址例項 IPEndPoint clientEP = new IPEndPoint (IPAddress.Parse (ip), port); //連線伺服器 clientSocket.Connect (clientEP); //第一個是快取 第二個 是從第幾個開始接受 第三個 接受多少個位元組 第四個 需不需要特殊的服務 第五個回撥函式 第六個當前物件 clientSocket.BeginReceive (clientBuffer, 0, this.clientBuffer.Length, SocketFlags.None, new System.AsyncCallback (clientReceive), this.clientSocket); } void clientReceive (System.IAsyncResult ar) { //獲取一個客戶端正在接受資料的物件 Socket workingSocket = ar.AsyncState as Socket; int byteCount = 0; string content = ""; try { //結束接受資料 完成儲存 byteCount = workingSocket.EndReceive (ar); } catch (SocketException ex) { //如果接受訊息失敗 clientReceiveCallBack (ex.ToString ()); } if (byteCount > 0) { //轉換已經接受到得Byte資料為字串 content = UTF8Encoding.UTF8.GetString (clientBuffer); } //傳送資料 clientReceiveCallBack (content); //接受下一波資料 clientSocket.BeginReceive (clientBuffer, 0, this.clientBuffer.Length, SocketFlags.None, new System.AsyncCallback (clientReceive), this.clientSocket); } public void ClientSendMessage (string msg) { if (msg != "") { //將要傳送的字串訊息轉換成BYTE陣列 clientBuffer = UTF8Encoding.UTF8.GetBytes (msg); } clientSocket.BeginSend (clientBuffer, 0, this.clientBuffer.Length, SocketFlags.None, new System.AsyncCallback (SendMsg), this.clientSocket); } void SendMsg (System.IAsyncResult ar) { Socket workingSocket = ar.AsyncState as Socket; workingSocket.EndSend (ar); } #endregion }
伺服器端
客戶端<span style="font-size:24px;">using UnityEngine; using System.Collections; public class ServerSocketDemo : MonoBehaviour { private LdySocket ldysocket; string serverContent; void Awake () { ldysocket = new LdySocket (); //執行初始化伺服器方法,傳入委託函式 ldysocket.InitServer (ShowMsg); } void ShowMsg (string msg) { serverContent = msg; } void OnGUI () { GUILayout.Label (serverContent); } } </span>
<span style="font-size:24px;">using UnityEngine;
using System.Collections;
public class ClientSocketDemo : MonoBehaviour
{
private LdySocket ldysocket;
private string clientContent;
private string needSendText = "";
void Awake ()
{
ldysocket = new LdySocket ();
ldysocket.InitClient ("127.0.0.1", 23456, (string msg) => {
clientContent = msg;
});
}
void OnGUI ()
{
needSendText = GUILayout.TextField (needSendText);
if (GUILayout.Button ("點擊發送訊息")) {
if (needSendText != "") {
ldysocket.ClientSendMessage (needSendText);
}
}
}
}</span>