1. 程式人生 > >Unity使用Socket與後臺連線,包含Json的讀寫

Unity使用Socket與後臺連線,包含Json的讀寫

在做遊戲開發,最近正在將前端與後臺連線,就寫一下筆記記錄一下吧!

我用的是Socket與後臺進行連線,資料的傳輸用的是Json格式。也是從零做起的,以前沒有與伺服器連線的經驗,所以也是結合了網上一些資料。首先說一下總體思路吧,這裡沒有用非同步,採用的是新建了執行緒,來接收資料,並存到佇列進行呼叫解析。

Socket的建立和連結:

using UnityEngine;
using System.Collections.Generic;
using System.Collections;using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

public class TcpClientHandler:MonoBehaviour
{
	Socket serverSocket; //伺服器端socket
	private string ClientIP = "192.168.1.139";//IP地址,改成自己的
	IPAddress ip; //主機ip
	IPEndPoint ipEnd;
	string recvStr; //接收的字串
	string sendStr; //傳送的字串
	byte[] recvData=new byte[1024]; //接收的資料,必須為位元組
	byte[] sendData=new byte[1024]; //傳送的資料,必須為位元組
	int recvLen = 0; //接收的資料長度
	Thread connectThread; //連線執行緒

	private Queue<string> queue = new Queue<string> ();//新建一個佇列,用來儲存伺服器發來的資料

	//伺服器初始化
	public void InitSocket()
	{
		ip=IPAddress.Parse(ClientIP);
		ipEnd=new IPEndPoint(ip,8009); //伺服器埠號,自己改
		
		//開啟一個執行緒連線
		connectThread=new Thread(new ThreadStart(SocketReceive));
		connectThread.Start();
	}

	//接收伺服器訊息
	void SocketConnet()
	{
		if(serverSocket!=null)
			serverSocket.Close();
		//定義套接字型別,必須在子執行緒中定義
		serverSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
		//連線
		serverSocket.Connect(ipEnd);

		recvLen=serverSocket.Receive(recvData);
		recvStr=Encoding.UTF8.GetString(recvData,0,recvLen);
		print(recvStr);
		queue.Enqueue (recvStr);
	}

	public void SocketSend(string sendStr)
	{
		//清空傳送快取
		sendData=new byte[1024];
		//資料型別轉換
		sendData=Encoding.UTF8.GetBytes(sendStr);
		//傳送
		serverSocket.Send(sendData,sendData.Length,SocketFlags.None);
	}

	void SocketReceive()
	{
		SocketConnet();
		//不斷接收伺服器發來的資料
		while(true)
		{
			recvData=new byte[1024];
			recvLen=serverSocket.Receive(recvData);
			if(recvLen==0)
			{
				SocketConnet();
				continue;
			}
			recvStr=Encoding.UTF8.GetString(recvData,0,recvLen);
			queue.Enqueue (recvStr);
			print(recvStr);
		}
	}

	//返回接收到的字串
	public string GetRecvStr()
	{
		string returnStr;
		//加鎖防止字串被改
		lock(this)
		{
			if (queue.Count > 0) {//佇列內有資料時,取出
				returnStr = queue.Dequeue ();
				return returnStr;
			}		}    
		return null;
	}

	public void SocketQuit()
	{
		//關閉執行緒
		if(connectThread!=null)
		{
			connectThread.Interrupt();
			connectThread.Abort();
		}
		//最後關閉伺服器
		if(serverSocket!=null)
		serverSocket.Close();
	}
}

然後在另一個指令碼啟動伺服器:
using UnityEngine;
using System.Collections;
using LitJson;
using UnityEngine.SceneManagement;

public class TcpTest:MonoBehaviour
{
	public static TcpTest _instance;
	TcpClientHandler tcpClient;
	JsonData returnDataJson;

	void Awake(){
		DontDestroyOnLoad (this.gameObject);
	}

	// Use this for initialization
	void Start()
	{
		//初始化網路連線
		//tcpClient=new TcpClientHandler(); 
		tcpClient=gameObject.AddComponent<TcpClientHandler>();
		tcpClient.InitSocket();
	}
		
	// Update is called once per frame
	void Update()
	{
		returnDataHandle ();
	}

	//伺服器返回訊息的處理
	void returnDataHandle(){
		returnData = tcpClient.GetRecvStr ();
		//print (returnData);
		if (returnData != null){
			returnDataJson = JsonMapper.ToObject (returnData);
			switch(returnDataJson["cmd"].ToString()){
				//在此處解析Json,如有專案需要,最好在其他指令碼編寫,此處只為方便
			}
		}
	}	

	void OnApplicationQuit()
	{
		//退出時關閉連線
		tcpClient.SocketQuit();
		print ("Quit");
	}

	public void closeC(){//此處比較關鍵,因為在我們除錯時,關閉程式Unity並不一定認為你是退出,所以上面程式碼也許不會執行,導致與伺服器一直連線,Unity崩潰
		tcpClient.SocketQuit();
		print ("closeC");
	}
}



最後說一下Json的處理,首先要匯入LitJson庫,然後在指令碼中using LitJson。

傳送資料舉例:

//註冊
	public void RegisterEvent(string username, string password){
		JsonData registerJson = new JsonData ();
		registerJson ["cmd"] = "Login|register";
		registerJson ["name"] = "wyq";
		registerJson ["tel"] = username;
		registerJson ["psd"] = password;

		string registrStr = registerJson.ToJson();
		tcpClient.SocketSend (registrStr);	
	}

接收的處理上面程式碼中已有部分介紹,在獲取json資料後,進行解析呼叫即可。