1. 程式人生 > >【Unity】Socket 同步與非同步

【Unity】Socket 同步與非同步

同步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>