1. 程式人生 > >Unity 客戶端網路架構 生產者消費者模式

Unity 客戶端網路架構 生產者消費者模式

假設我們的資料包是這樣的結構

[Serializable] //序列化物件 [StructLayout(LayoutKind.Sequential, Pack = 1)] // 按1位元組對齊 public class UserMsg {     public int messageID;     public int clientID;     [MarshalAs(UnmanagedType.ByValArray, SizeConst = 200)] //限制200位元組     public byte[] message; }

我們在客戶端為了避免IO阻塞所以應該新建一個子執行緒來接收資料包

之所以使用生產者消費者模式有三個點

1.當資料包傳送量大的時候,容易造成message堆積,每次都要等管理員處理完上一個訊息才能接收下一個訊息

2.執行緒中無法呼叫Unity許多方法,比如GameObject.Find("");所以我們需要一個置身事外的老哥來處理這些雜七雜八的事情

3.network只應該負責接收訊息、傳遞訊息而不能在其中處理訊息,這種設計模式是不好的

所以我們打算採用類似於GPU和CPU的流水線模式,一個負責生產訊息,一個負責處理訊息

初始化客戶端以後新建一個執行緒,負責接收訊息, 接收完畢把訊息傳遞到訊息佇列

生產者從一邊生產訊息,消費者從另一邊消費訊息

 Thread t = new Thread(new ThreadStart(()=> {
            while (true)
            {
                UserMsg u = receiveMessage();
               receive(u);
           }
        }));
        t.Start();

下面是委託的定義和初始化

    public delegate void receiveHandler(UserMsg u);
    public event receiveHandler receive;

    public ClientNetWork() {
        receive += new receiveHandler(ClientAdministrator.newMessage);
    }

訊息佇列和管理員處理訊息的方法

public class ClientAdministrator : MonoBehaviour
{
    public static Queue<UserMsg> u=new Queue<UserMsg>();
    public static void newMessage(UserMsg user) {
        u.Enqueue(user);
    }
    public static void DealWithMessage(){
        //消費者消費一條訊息
        UserMsg user=u.Dequeue();
        Debug.Log("消費者消費了一條訊息");
    }
    private void Start()
    {
        
    }
    private void Update()
    {
        if (u.Count>0) {
            DealWithMessage();
        }
    }
}

假設我生產一條訊息的時間是10分鐘,消費一條訊息的時間是f(x)(x為訊息的大小)

那麼原始設計模式客戶端每次處理一條訊息的時間是10+f(x)

使用上述設計模式,客戶端處理訊息的速度恆為f(x),而且消費者可以直接操作unity物件方法