把服务器端的Message类复制到unity工程下并进行修改:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using Common;
class Message
{
private byte[] data = new byte[1024]; //这个数组用来存取我们读取到的数据,让消息的长度最少能存的下1024 ,如果说最大的消息数组存不下的话 就没办法完整的读取这条消息了
//如果消息不完整 我们不处理。我们会读取下一条
private int startIndex = 0;//标识位,表示现在数据存储在什么位置了 ,如果没数据 sartIndex从0开始,如果存了10个之后 这个startIndex就等于10;
//再来数据的话就从10开始存,同时也代表了存了多少个字节的数据。
///
/// 这个数组用来存取我们读取到的数据
///
public byte[] Data
{
get { return data; }
}
///
/// 代表存储了多少个字节的数据 开始索引
///
public int StartIndex
{
get { return startIndex; }
}
///
/// 剩余的空间
///
public int RemaniSize
{
get { return data.Length - startIndex; }
}
///
/// 更新了多少数据
///
///
//public void AddCount(int count)
//{
// startIndex += count;
//}
///
/// 解析数据或者叫做读取数据 newDataAmount数量
///
public void ReadMessage(int newDataAmount, Action processDataCallback)
{
startIndex += newDataAmount;
while (true)
{
if (startIndex <= 4) return;
int count = BitConverter.ToInt32(data, 0);//这个只占前四个字节 ,变成int 就是数据长度
if ((startIndex - 4) >= count) //(startIndex-4)是剩余数据的长度 ,大于count 就说明数据是完整的
{
//string s = Encoding.UTF8.GetString(data, 4, count);
//Console.WriteLine("解析出来一条数据 :" + s);
RequesCode requestCode = (RequesCode)BitConverter.ToInt32(data, 4); ///解析出来的是ResourceCode
ActionCode actionCode = (ActionCode)BitConverter.ToInt32(data, 8); ///解析出来的是ActionCode
string s = Encoding.UTF8.GetString(data, 12, count - 8);
processDataCallback(requestCode, actionCode, s);
Array.Copy(data, count + 4, data, 0, startIndex - 4 - count);
startIndex -= (count + 4); //移动完了之后更新startIndex
}
else
{
break;
}
}
}
///
/// 用于包装
///
///
///
///
public static byte[] PakeData(RequesCode requsetData,ActionCode actionCode, string data)
{
byte[] requsetCodeBytes = BitConverter.GetBytes((int)requsetData);
byte[] actionCodeBytes = BitConverter.GetBytes((int)actionCode);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
int dataAmount = requsetCodeBytes.Length + dataBytes.Length+actionCodeBytes.Length;
byte[] dataAmountBytes = BitConverter.GetBytes(dataAmount);
return dataAmountBytes.Concat(requsetCodeBytes).ToArray().Concat(actionCodeBytes).ToArray().Concat(dataBytes).ToArray();
}
///
/// 用于包装
///
///
///
///
public static byte[] PakeData(RequesCode requsetData, string data)
{
byte[] requsetCodeBytes = BitConverter.GetBytes((int)requsetData);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
int dataAmount = requsetCodeBytes.Length + dataBytes.Length;
byte[] dataAmountBytes = BitConverter.GetBytes(dataAmount);
return dataAmountBytes.Concat(requsetCodeBytes).Concat(dataBytes).ToArray();
}
}
ClinetManager类也做一些修改 :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using UnityEngine;
using Common;
///
/// 这个是用来管理跟服务器端的Socket连接
///
public class ClientManager:BaseManager
{
public const string IP = "127.0.0.1";
public const int PORT = 6688;
private Socket clinetSocket;
public override void OnInit()
{
base.OnInit();
clinetSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clinetSocket.Connect(IP, PORT);
}
catch (Exception e)
{
Debug.LogWarning("无法连接到服务器端请检查你的网络"+e);
}
}
public void SendRequest(RequesCode requesCode, ActionCode actionCode, string data)
{
byte[] bytes = Message.PakeData(requesCode, actionCode, data);
clinetSocket.Send(bytes);
}
public override void OnDestory()
{
base.OnDestory();
try
{
clinetSocket.Close();
}
catch (Exception e)
{
Debug.LogWarning("无法关闭跟服务端的连接" + e);
}
}
}
修改客户端的Message类 解析消息 进行修修改
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//using System.Threading.Tasks;
using Common;
class Message
{
private byte[] data = new byte[1024]; //这个数组用来存取我们读取到的数据,让消息的长度最少能存的下1024 ,如果说最大的消息数组存不下的话 就没办法完整的读取这条消息了
//如果消息不完整 我们不处理。我们会读取下一条
private int startIndex = 0;//标识位,表示现在数据存储在什么位置了 ,如果没数据 sartIndex从0开始,如果存了10个之后 这个startIndex就等于10;
//再来数据的话就从10开始存,同时也代表了存了多少个字节的数据。
///
/// 这个数组用来存取我们读取到的数据
///
public byte[] Data
{
get { return data; }
}
///
/// 代表存储了多少个字节的数据 开始索引
///
public int StartIndex
{
get { return startIndex; }
}
///
/// 剩余的空间
///
public int RemaniSize
{
get { return data.Length - startIndex; }
}
///
/// 更新了多少数据
///
///
//public void AddCount(int count)
//{
// startIndex += count;
//}
///
/// 解析数据或者叫做读取数据 newDataAmount数量
///
public void ReadMessage(int newDataAmount, Action processDataCallback)
{
startIndex += newDataAmount;
while (true)
{
if (startIndex <= 4) return;
int count = BitConverter.ToInt32(data, 0);//这个只占前四个字节 ,变成int 就是数据长度
if ((startIndex - 4) >= count) //(startIndex-4)是剩余数据的长度 ,大于count 就说明数据是完整的
{
//string s = Encoding.UTF8.GetString(data, 4, count);
//Console.WriteLine("解析出来一条数据 :" + s);
RequesCode requestCode = (RequesCode)BitConverter.ToInt32(data, 4); ///解析出来的是ResourceCode
ActionCode actionCode = (ActionCode)BitConverter.ToInt32(data, 8); ///解析出来的是ActionCode
string s = Encoding.UTF8.GetString(data, 8, count - 4);
processDataCallback(requestCode, s);
Array.Copy(data, count + 4, data, 0, startIndex - 4 - count);
startIndex -= (count + 4); //移动完了之后更新startIndex
}
else
{
break;
}
}
}
///
/// 用于包装
///
///
///
///
public static byte[] PakeData(RequesCode requsetData,ActionCode actionCode, string data)
{
byte[] requsetCodeBytes = BitConverter.GetBytes((int)requsetData);
byte[] actionCodeBytes = BitConverter.GetBytes((int)actionCode);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
int dataAmount = requsetCodeBytes.Length + dataBytes.Length+actionCodeBytes.Length;
byte[] dataAmountBytes = BitConverter.GetBytes(dataAmount);
return dataAmountBytes.Concat(requsetCodeBytes).ToArray().Concat(actionCodeBytes).ToArray().Concat(dataBytes).ToArray();
}
///
/// 用于包装
///
///
///
///
public static byte[] PakeData(RequesCode requsetData, string data)
{
byte[] requsetCodeBytes = BitConverter.GetBytes((int)requsetData);
byte[] dataBytes = Encoding.UTF8.GetBytes(data);
int dataAmount = requsetCodeBytes.Length + dataBytes.Length;
byte[] dataAmountBytes = BitConverter.GetBytes(dataAmount);
return dataAmountBytes.Concat(requsetCodeBytes).Concat(dataBytes).ToArray();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using UnityEngine;
using Common;
///
/// 这个是用来管理跟服务器端的Socket连接
///
public class ClientManager:BaseManager
{
public const string IP = "127.0.0.1";
public const int PORT = 6688;
private Socket clinetSocket;
private Message message = new Message();
public override void OnInit()
{
base.OnInit();
clinetSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clinetSocket.Connect(IP, PORT);
Start();
}
catch (Exception e)
{
Debug.LogWarning("无法连接到服务器端请检查你的网络"+e);
}
}
///
/// 开始监听
///
private void Start()
{
clinetSocket.BeginReceive(message.Data, message.StartIndex, message.RemaniSize, SocketFlags.None, AsyncCallback, null);
}
public void AsyncCallback(IAsyncResult ar)
{
try
{
int count = clinetSocket.EndReceive(ar);
message.ReadMessage(count, OnProcessDataCallback);
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
public void SendRequest(RequesCode requesCode, ActionCode actionCode, string data)
{
byte[] bytes = Message.PakeData(requesCode, actionCode, data);
clinetSocket.Send(bytes);
}
///
/// 回调方法
///
public void OnProcessDataCallback(RequesCode requesCode,string data)
{
//TODO
}
public override void OnDestory()
{
base.OnDestory();
try
{
clinetSocket.Close();
}
catch (Exception e)
{
Debug.LogWarning("无法关闭跟服务端的连接" + e);
}
}
}
如图所示,
让BaseManager持有GameFacade引用 让子类能访问:
BaseManager类:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BaseManager {
protected GameFacade facade;
public BaseManager(GameFacade facade)
{
this.facade = facade;
}
///
/// 生命的开始
///
public virtual void OnInit() { }
///
/// 生命的结束
///
public virtual void OnDestory() { }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class AudioManager:BaseManager
{
public AudioManager(GameFacade facade):base (facade)
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class AudioManager:BaseManager
{
public AudioManager(GameFacade facade):base (facade)
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class PlayerManager:BaseManager
{
public PlayerManager(GameFacade facade):base (facade)
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public class RequestManager :BaseManager
{
public RequestManager(GameFacade facade):base (facade)
{
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using UnityEngine;
using Common;
///
/// 这个是用来管理跟服务器端的Socket连接
///
public class ClientManager:BaseManager
{
public ClientManager(GameFacade facade):base (facade)
{
}
public const string IP = "127.0.0.1";
public const int PORT = 6688;
private Socket clinetSocket;
private Message message = new Message();
public override void OnInit()
{
base.OnInit();
clinetSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clinetSocket.Connect(IP, PORT);
Start();
}
catch (Exception e)
{
Debug.LogWarning("无法连接到服务器端请检查你的网络"+e);
}
}
///
/// 开始监听
///
private void Start()
{
clinetSocket.BeginReceive(message.Data, message.StartIndex, message.RemaniSize, SocketFlags.None, AsyncCallback, null);
}
public void AsyncCallback(IAsyncResult ar)
{
try
{
int count = clinetSocket.EndReceive(ar);
message.ReadMessage(count, OnProcessDataCallback);
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
public void SendRequest(RequesCode requesCode, ActionCode actionCode, string data)
{
byte[] bytes = Message.PakeData(requesCode, actionCode, data);
clinetSocket.Send(bytes);
}
///
/// 回调方法
///
public void OnProcessDataCallback(RequesCode requesCode,string data)
{
//TODO
}
public override void OnDestory()
{
base.OnDestory();
try
{
clinetSocket.Close();
}
catch (Exception e)
{
Debug.LogWarning("无法关闭跟服务端的连接" + e);
}
}
}
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System;
public class UIManager:BaseManager {
///
/// 单例模式的核心
/// 1,定义一个静态的对象 在外界访问 在内部构造
/// 2,构造方法私有化
//private static UIManager _instance;
//public static UIManager Instance
//{
// get
// {
// if (_instance == null)
// {
// _instance = new UIManager();
// }
// return _instance;
// }
//}
private Transform canvasTransform;
private Transform CanvasTransform
{
get
{
if (canvasTransform == null)
{
canvasTransform = GameObject.Find("Canvas").transform;
}
return canvasTransform;
}
}
private Dictionary panelPathDict;//存储所有面板Prefab的路径
private Dictionary panelDict;//保存所有实例化面板的游戏物体身上的BasePanel组件
private Stack panelStack;
public UIManager(GameFacade facade):base(facade)
{
ParseUIPanelTypeJson();
}
///
/// 把某个页面入栈, 把某个页面显示在界面上
///
public void PushPanel(UIPanelType panelType)
{
if (panelStack == null)
panelStack = new Stack();
//判断一下栈里面是否有页面
if (panelStack.Count > 0)
{
BasePanel topPanel = panelStack.Peek();
topPanel.OnPause();
}
BasePanel panel = GetPanel(panelType);
panel.OnEnter();
panelStack.Push(panel);
}
///
/// 出栈 ,把页面从界面上移除
///
public void PopPanel()
{
if (panelStack == null)
panelStack = new Stack();
if (panelStack.Count <= 0) return;
//关闭栈顶页面的显示
BasePanel topPanel = panelStack.Pop();
topPanel.OnExit();
if (panelStack.Count <= 0) return;
BasePanel topPanel2 = panelStack.Peek();
topPanel2.OnResume();
}
///
/// 根据面板类型 得到实例化的面板
///
///
private BasePanel GetPanel(UIPanelType panelType)
{
if (panelDict == null)
{
panelDict = new Dictionary();
}
//BasePanel panel;
//panelDict.TryGetValue(panelType, out panel);//TODO
BasePanel panel = panelDict.TryGet(panelType);
if (panel == null)
{
//如果找不到,那么就找这个面板的prefab的路径,然后去根据prefab去实例化面板
//string path;
//panelPathDict.TryGetValue(panelType, out path);
string path = panelPathDict.TryGet(panelType);
GameObject instPanel = GameObject.Instantiate(Resources.Load(path)) as GameObject;
instPanel.transform.SetParent(CanvasTransform,false);
panelDict.Add(panelType, instPanel.GetComponent());
return instPanel.GetComponent();
}
else
{
return panel;
}
}
[Serializable]
class UIPanelTypeJson
{
public List infoList;
}
private void ParseUIPanelTypeJson()
{
panelPathDict = new Dictionary();
TextAsset ta = Resources.Load("UIPanelType");
UIPanelTypeJson jsonObject = JsonUtility.FromJson(ta.text);
foreach (UIPanelInfo info in jsonObject.infoList)
{
//Debug.Log(info.panelType);
panelPathDict.Add(info.panelType, info.path);
}
}
///
/// just for test
///
public void Test()
{
string path ;
panelPathDict.TryGetValue(UIPanelType.Knapsack,out path);
Debug.Log(path);
}
}
代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Common;
public class BaseRequest : MonoBehaviour {
private RequesCode requestCode = RequesCode.None;
// Use this for initialization
public virtual void Awake () {
}
public virtual void SendRequest()
{
}
public virtual void OnResponse(string data)
{
}
}
RequestManager类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
public class RequestManager :BaseManager
{
private Dictionary requestDict = new Dictionary();
public RequestManager(GameFacade facade):base (facade)
{
}
public void AddRequets(RequesCode requestCode,BaseRequest baseRequest)
{
requestDict.Add(requestCode, baseRequest);
}
public void RemoveRequest(RequesCode requestCode)
{
requestDict.Remove(requestCode );
}
}
using Common;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameFacade : MonoBehaviour {
private static GameFacade _instance;
public static GameFacade Instance { get { return _instance; } }
void Awake()
{
if (_instance!=null)
{
Destroy(this.gameObject);return;
}
_instance = this;
}
private UIManager uiMng;
private AudioManager audioMng;
private PlayerManager playerMng;
private CameraManager cameraMng;
private RequestManager requesMng;
private ClientManager clientMng;
void Start () {
InitManager();
}
// Update is called once per frame
void Update () {
}
private void InitManager()
{
uiMng = new UIManager(this);
audioMng = new AudioManager(this);
playerMng = new PlayerManager(this);
cameraMng = new CameraManager(this);
requesMng = new RequestManager(this);
clientMng = new ClientManager(this);
uiMng.OnInit();
audioMng.OnInit();
playerMng.OnInit();
cameraMng.OnInit();
requesMng.OnInit();
clientMng.OnInit();
}
private void DestoryManager()
{
uiMng.OnDestory();
audioMng.OnDestory();
playerMng.OnDestory();
cameraMng.OnDestory();
requesMng.OnDestory();
clientMng.OnDestory();
}
private void OnDestory()
{
DestoryManager();
}
public void AddRequets(RequesCode requestCode, BaseRequest baseRequest)
{
requesMng.AddRequets(requestCode, baseRequest);
}
public void RemoveRequest(RequesCode requestCode)
{
requesMng.RemoveRequest(requestCode);
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Common;
public class BaseRequest : MonoBehaviour {
private RequesCode requestCode = RequesCode.None;
// Use this for initialization
public virtual void Awake () {
GameFacade.Instance.AddRequets(requestCode, this);
}
public virtual void SendRequest()
{
}
public virtual void OnResponse(string data)
{
}
public virtual void OnDestory()
{
GameFacade.Instance.RemoveRequest(requestCode);
}
}
修改RequestManager 处理消息:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Common;
using UnityEngine;
public class RequestManager :BaseManager
{
private Dictionary requestDict = new Dictionary();
public RequestManager(GameFacade facade):base (facade)
{
}
public void AddRequets(RequesCode requestCode,BaseRequest baseRequest)
{
requestDict.Add(requestCode, baseRequest);
}
public void RemoveRequest(RequesCode requestCode)
{
requestDict.Remove(requestCode );
}
///
/// 处理相应
///
public void HandleRepones(RequesCode requesCode ,string data)
{
BaseRequest request = requestDict.TryGet(requesCode);
if (request==null)
{
Debug.Log("无法得到RequestCode" + requesCode + "对应的Request类");return;
} /// 处理服务端相应
request.OnResponse(data);
}
}
然后再修改GameFacade类:
using Common;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class GameFacade : MonoBehaviour {
private static GameFacade _instance;
public static GameFacade Instance { get { return _instance; } }
void Awake()
{
if (_instance!=null)
{
Destroy(this.gameObject);return;
}
_instance = this;
}
private UIManager uiMng;
private AudioManager audioMng;
private PlayerManager playerMng;
private CameraManager cameraMng;
private RequestManager requesMng;
private ClientManager clientMng;
void Start () {
InitManager();
}
// Update is called once per frame
void Update () {
}
private void InitManager()
{
uiMng = new UIManager(this);
audioMng = new AudioManager(this);
playerMng = new PlayerManager(this);
cameraMng = new CameraManager(this);
requesMng = new RequestManager(this);
clientMng = new ClientManager(this);
uiMng.OnInit();
audioMng.OnInit();
playerMng.OnInit();
cameraMng.OnInit();
requesMng.OnInit();
clientMng.OnInit();
}
private void DestoryManager()
{
uiMng.OnDestory();
audioMng.OnDestory();
playerMng.OnDestory();
cameraMng.OnDestory();
requesMng.OnDestory();
clientMng.OnDestory();
}
private void OnDestory()
{
DestoryManager();
}
public void AddRequets(RequesCode requestCode, BaseRequest baseRequest)
{
requesMng.AddRequets(requestCode, baseRequest);
}
public void RemoveRequest(RequesCode requestCode)
{
requesMng.RemoveRequest(requestCode);
}
///
/// 处理相应
///
public void HandleRepones(RequesCode requesCode, string data)
{
requesMng.HandleRepones(requesCode, data);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Net;
using UnityEngine;
using Common;
///
/// 这个是用来管理跟服务器端的Socket连接
///
public class ClientManager:BaseManager
{
public ClientManager(GameFacade facade):base (facade)
{
}
public const string IP = "127.0.0.1";
public const int PORT = 6688;
private Socket clinetSocket;
private Message message = new Message();
public override void OnInit()
{
base.OnInit();
clinetSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
clinetSocket.Connect(IP, PORT);
Start();
}
catch (Exception e)
{
Debug.LogWarning("无法连接到服务器端请检查你的网络"+e);
}
}
///
/// 开始监听
///
private void Start()
{
clinetSocket.BeginReceive(message.Data, message.StartIndex, message.RemaniSize, SocketFlags.None, AsyncCallback, null);
}
public void AsyncCallback(IAsyncResult ar)
{
try
{
int count = clinetSocket.EndReceive(ar);
message.ReadMessage(count, OnProcessDataCallback);
//继续监听
Start();
}
catch (Exception e)
{
Debug.Log(e.ToString());
}
}
public void SendRequest(RequesCode requesCode, ActionCode actionCode, string data)
{
byte[] bytes = Message.PakeData(requesCode, actionCode, data);
clinetSocket.Send(bytes);
}
///
/// 回调方法
///
public void OnProcessDataCallback(RequesCode requesCode,string data)
{
GameFacade.Instance.HandleRepones(requesCode, data);
//TODO
}
public override void OnDestory()
{
base.OnDestory();
try
{
clinetSocket.Close();
}
catch (Exception e)
{
Debug.LogWarning("无法关闭跟服务端的连接" + e);
}
}
}