• 熱門專題

開發日記-_-优行网交通违章查询:KBEngine+Unity+php做個撲克小遊戲DAY2

作者||舒友阁养阴宝:  發布日期--诺基亚3208:2016-11-14 20:23:55
Tag標簽__11086移动彩票客户端:撲克  小遊戲  日記  
  • 怎麼辦|_诺基亚1110手机,這很尷尬||_永盛娱乐平台赛车,為啥呢_|聚返吧,因為kbe的某些原因讓我放棄了使用它所以本打算繼續更新的_-|众购彩票官方网站,說一下原因-|-mc擦皮鞋歌词:

    在DAY1中我希望kbe能夠開啟一個http服務__-工作总结结尾,並讓php端做一個web請求將消息傳遞給對應的用戶|--众赢彩票国家是否承认,可是這個http服務我是寫起來了-|-陕西省职业技能鉴定指导中心,發送消息的函數也寫出來(花了不少時間||_深圳股市大盘,kbe的注釋和文檔都不多|-永安彩票做代刷可靠吗?,特別是kbe把BaseHttpServer這個python庫另外弄了個名字-__李白 谈爱,用http.server import as 才導入成功)尷尬的就是http服務和發消息的函數怎麼也放不到一起-||僵尸围城怎么做:

    1.一旦某個class不繼承自KBEngine.Base,那麼他就無法訪問KBEngine的幾乎所有靜態函數|-2628彩票天天签到、屬性___腾讯包钢股份,就無法獲取到對應用戶的mailbox完成消息發送

    2.一旦繼承KBEgine.Base-好听的韩国手机铃声,你就做不了HTTP 服務-_约彩彩票靠谱吗,因為你的handler必須繼承baseHandler_||双色球精准预测6十1,你繼承不了||-运盛娱乐平台登录,且即使你繼承到baseHandler去訪問KBEgine.Base的mailbox之類的又回到剛的死邏輯之中

    3.係統庫的HTTP服務會阻塞進程|-105彩票苹果系统,這個文檔還是寫了-_2m永久免费开奖,不過替代框架太麻煩_北上广地铁神器,且調試太不方便__轻叩诗歌的大门ppt,且語法太熟悉|--至尊彩链接,且…………雖然我想說一萬個且_|郭美美澳门欠赌债,隻能說明我無能啊…………

    當然論壇和官網當中也有人反應類似的問題|_长春新天地电影院,例如第三方接口訪問KBE的成員/屬性問題___英达锐香港入口网站,不過看起來好像並沒有現成的解決方案_掌上娱乐app,最後的最後|_双鹿空调故障代码。__往日时光吉他谱。|_草配药禁忌。我放棄了

     

    然後呢~~我自己老老實實寫了一個消息服務器(基於socket |攻坚朱诺,with WPF .net 4.5+)以及消息協議

    消息協議采用http://msgpack.org/ 基本上支援所有的語言|美知广子猝死录像,因此實際上我這個消息服務器可以服務任何類型的客戶端-|-野上凉华,不管你啥平台啥語言

     

    1.0版協議(還沒名字呢)規定:

    1.BasePack代表發送的包--12306智行火车电话,BaseAckPack代表回執包-爱唯侦察网址,BaseAckPack繼承自BasePack

    2.每個Pack長度為1024字節--金华烟草电子商务网,且第0~4字節轉換成int代表pack類型-__野兽汽车, BasePack及其子類從1.2.3...10... BaseAckPack 及其子類從1001,1002,1003...1010...(有考慮負數--本草仙目,其實應該也ok)

    為啥這樣做|_魏征进谏图的作者是谁? 這裏很奇特-|实况8妖人,你在把這1024個字節用msgpack轉成對象之前|_索爱595,你並不知道這個pack是哪個對象|3cp上彩票,你不能統一按某一個特定的對象去轉|-五月色桃色激情婷婷,比如LoginPack比BasePack隻多了2個屬性--_咖啡恋人,你在不知道它是一個LoginPack還是一個BasePack之前_|-银河战士融合金手指,你無法拆開他-|补补补歌词,你按任何一種來拆開都有可能出錯(屬性多了或少了-||赢彩天下,熟悉iOS 的KVC的應該很清楚)-_|石家庄口碑网,所以必須先把前麵4個字節騰出來安万克,可選的_|衡水一中录取分数线,第5~8個字節放長度(mespack可以長度大於內容拆開沒問題)_||v880刷机包,讀8個字節之後再讀剩下的1016(當然不一定每個包一定得是1024_||7k7k7k7k7k小游戏,可以更大__流浪的蛤蟆蜀山,畢竟我目前夠用了)個字節

     

    using System;
    //send包
    namespace Packs
    {
        //基礎包
        public class BasePack<T>
        {
            public int packType;
            public int fromId;
            public int toId;
            public int messageId;
            //將基本包轉bytes
            public byte[] PackToBytes()
            {
                var encode = MsgPack.Serialization.MessagePackSerializer.Get<T>();
                byte[] packContent = encode.PackSingleObject(this);
                byte[] type = BasePack.intToBytes(this.packType);
                byte[] len = BasePack.intToBytes(packContent.Length);
                int lenth = packContent.Length;
    
    
                byte[] dest = new byte[1024];
    
                //第一個int空間-|-陈明月爱情连连看:類型
                Buffer.BlockCopy(type, 0, dest, 0, type.Length);
    
                //第二個int空間--手机qq2009下载:長度
                Buffer.BlockCopy(len, 0, dest, type.Length, len.Length);
                
                //剩餘空間-360彩票导航走势图大全:包內容
                Buffer.BlockCopy(packContent, 0, dest, type.Length+len.Length, packContent.Length);
    
                Console.WriteLine("打包pack,類型:" + this.packType + "長度:" + packContent.Length);
    
                return dest;
            }
    
            //將bytes轉回基本包
            public static T BytesToPack(byte[] bytes)
            {
                var encode = MsgPack.Serialization.MessagePackSerializer.Get<T>();
                return encode.UnpackSingleObject(bytes);
            }
    
    
    
        }
    
        public class BasePack:BasePack<BasePack>
        {
            public const int LOGIN_PACK = 1;
            public const int REGISTER_PACK = 2;
            public const int PING_PACK = 3;
            public const int PONG_PACK = 4;
            public const int TEXT_PACK = 5;
            public const int SYSTEM_PUSH_PACK = 6;
    
            public const int LOGIN_ACK = 1001;
            public const int REGISTER_ACK = 1002;
            public const int PING_ACK = 1003;
            public const int PONG_ACK = 1004;
            public const int TEXT_ACK = 1005;
            public const int SYSTEM_PUSH_ACK = 1006;
            public const int CONNECTED_ACK = 1007;
    
           
    
            /**  
    * 將int數值轉換為占四個字節的byte數組_-运盛彩票官网,本方法適用於(低位在前--_111端口漏洞,高位在後)的順序_阆中市国土局。  
    * @param value  
    *            要轉換的int值 
    * @return byte數組 
    */
            public static byte[] intToBytes(int value)
            {
                byte[] byte_src = new byte[4];
                byte_src[3] = (byte)((value & 0xFF000000) >> 24);
                byte_src[2] = (byte)((value & 0x00FF0000) >> 16);
                byte_src[1] = (byte)((value & 0x0000FF00) >> 8);
                byte_src[0] = (byte)((value & 0x000000FF));
                return byte_src;
            }
    
            /**  
           * byte數組中取int數值--vivos7t手机报价,本方法適用於(低位在前_|都匀蓝宇装饰,高位在後)的順序|_|5个人出名了。 
           *   
           * @param ary  
           *            byte數組  
           * @param offset  
           *            從數組的第offset位開始  
           * @return int數值  
           */
            public static int bytesToInt(byte[] ary, int offset)
            {
                int value;
                value = (int)((ary[offset] & 0xFF)
                        | ((ary[offset + 1] << 8) & 0xFF00)
                        | ((ary[offset + 2] << 16) & 0xFF0000)
                        | ((ary[offset + 3] << 24) & 0xFF000000));
                return value;
            }
        }
    
        //1.登錄包
        public class LoginPack: BasePack<LoginPack>
        {
            public string username;
            public string password;
    
            public LoginPack()
            {
                this.packType = BasePack.LOGIN_PACK;
            }
    
        }
    
    
        //5.文字包
        public class TextPack:BasePack<TextPack>
        {
            public string content;
            public string toUser;
            public string fromUser;
    
            public TextPack() {
                this.packType = BasePack.TEXT_PACK;
            }
        }
    
        //6.係統推送包
        public class SystemPushPack: BasePack<SystemPushPack>
        {
            public string content;
            public string toUser;
      
            public SystemPushPack()
            {
                this.packType = BasePack.SYSTEM_PUSH_PACK;
            }
        }
    
       
    }
    


     

     

    3.server端Accept之後立即發送ConnectPack,客戶端收到後發送ConnectAckPack完成連接

     

     private void OnAccept()
        {
    
            while (this.isServing)
            {
                //異步Accept 回調ConnEnd
                //serverSocket.BeginAccept(new System.AsyncCallback(this.ConnEnd), null);
    
                //同步Accept
                Socket clientSocket = serverSocket.Accept();
    
                ReceiveObject obj = new ReceiveObject();
                obj.acceptClient = clientSocket;
                clients.Add(obj);
    
                Thread receiveThread = new Thread(OnReceive);
                receiveThread.Start(obj);
    
                cThreads.Add(clientSocket.RemoteEndPoint.ToString(), receiveThread);
                Console.WriteLine("新的客戶端連接:" + clientSocket.RemoteEndPoint.ToString());
    
                BaseACKPack pack = new BaseACKPack();
                pack.packType = BasePack.CONNECTED_ACK;
    
                clientSocket.Send(pack.PackToBytes());
            }
        }


     

     

    4.客戶端發送LoginPack(由於php已經校驗了用戶名和密碼並且生成了token||苗条梅,所以loginPack實際上我沒有寫校驗密碼的邏輯--_北斗信号源,單純的綁定用戶名_--子龙郡,用來接收消息)-|猪肉概念股,server端拆開pack將用戶名綁定到客戶端對象中_永胜国际是投彩么,這個對象的內容如下___亿乐彩下载app:

     

     

    using System.Net.Sockets;
    public class ReceiveObject
    {
        public Socket acceptClient;
        public byte[] buffer = new byte[1024];
        public string userId;
        public string userName;
        public int roomId;
    
        public ReceiveObject()
        {
    
        }
    }

     

     

    整個處理函數||阿克苏诺贝尔 待遇:

     

        private void OnReceive(object obj)
        {
    
            while (this.isServing)
            {
    
                ReceiveObject e = obj as ReceiveObject;
                Socket c = e.acceptClient;
                e.buffer = new byte[1024];
    
                //判斷包類型-__乐都信息港,固定包在包之前
                int type = c.Receive(e.buffer, 0, sizeof(Int32), SocketFlags.None);
                if (type == 0)
                {
    
                    Console.WriteLine("客戶端斷開連接:" + c.RemoteEndPoint.ToString());
    
                    //clients.RemoveAll((ReceiveObject obj) => { return obj.acceptClient == 0 ? true : false; });
                    clients.Remove(e);
                    cThreads.Remove(c.RemoteEndPoint.ToString());
                    Thread.CurrentThread.Abort();
                    //斷開連接
                    c.Shutdown(SocketShutdown.Both);
                    c.Close();
                    break;
    
                }
    
                type = BasePack.bytesToInt(e.buffer, 0);
                //獲得包大小|||斯丽,固定第2個int
                int len = c.Receive(e.buffer, 0, sizeof(Int32), SocketFlags.None);
                len = BasePack.bytesToInt(e.buffer, 0);
                int receiveNumber = c.Receive(e.buffer, 0, 1024 - sizeof(Int32) * 2, SocketFlags.None);
    
                switch (type)
                {
                    case BasePack.LOGIN_PACK:
                        {
                            LoginPack lPack = LoginPack.BytesToPack(e.buffer);
                            Console.WriteLine("收到登錄請求,用戶名:" + lPack.username + "密碼:" + lPack.password);
    
                            e.userName = lPack.username;
    
                            //發送登錄ACK
                            LoginACKPack loginACK = new LoginACKPack();
                            //loginACK.success = true;
    
                            c.Send(loginACK.PackToBytes());
                        }
                        break;
                    case BasePack.TEXT_PACK:
                        {
                            //處理消息包
                            TextPack pack = TextPack.BytesToPack(e.buffer);
                            //處理basePack
                            Console.WriteLine("發送給" + pack.toUser + "的消息:" + pack.content);
    
                            //從clients組找用戶
                            List<ReceiveObject> list = clients.FindAll((ReceiveObject o) => { return o.userName == pack.toUser ? true : false; });
    
                            foreach (ReceiveObject target in list)
                            {
                                target.acceptClient.Send(pack.PackToBytes());
                            }
    
                        }
                        break;
                    case BasePack.TEXT_ACK:
                        {
                            //處理消息回執
                            TextACKPack pack = TextACKPack.BytesToPack(e.buffer);
    
                            //刪除對應的消息
    
                            pusher.DeleteMessageById(pack.messageId);
    
                        }
                        break;
                    case BasePack.SYSTEM_PUSH_ACK:
                        {
                            SystemPushACKPack pack = SystemPushACKPack.BytesToPack(e.buffer);
    
                            //刪除對應的消息
                            pusher.DeleteMessageById(pack.messageId);
                        }
                        break;
                    default:
                        //處理未知包
                        {
    
                        }
                        break;
                }
    
            }
        }

    發送消息函數|-长郡中学网站,目前寫了2個case 原因||苏州消防网:php端的推送類型很多-|尊龙国际娱乐平台app,我直接寫在pushPack的content內部__|158计划网时时彩,客戶端用json解析開就行了_|-198彩人工带玩,然後做了一個單聊的文本消息發送_500g是多少斤,按群組推還沒來得及做_-反间谍工作的主管单位:

     

     

        public void SendMsg(string from, string to, string body, int type, int messageId)
        {
            //從clients組找用戶
            ReceiveObject target = clients.FindLast((ReceiveObject o) => { return o.userName == to ? true : false; });
            if (target == null) return;
            //推送一條消息至客戶端
            //收到回執後才能修改sent狀態為1
            Console.WriteLine("推送消息給:" + to + "類型:" + type + "內容:" + body + "id:" + messageId);
            switch (type)
            {
    
                //推送文字消息
                case BasePack.TEXT_PACK:
                    {
                        TextPack txtPack = new TextPack();
                        txtPack.fromUser = from;
                        txtPack.toUser = to;
                        txtPack.content = body;
                        txtPack.messageId = messageId;
    
                        target.acceptClient.Send(txtPack.PackToBytes());
    
                    }
                    break;
                //係統消息
                case BasePack.SYSTEM_PUSH_PACK:
                    {
                        SystemPushPack txtPack = new SystemPushPack();
    
                        txtPack.toUser = to;
                        txtPack.content = body;
                        txtPack.messageId = messageId;
    
                        target.acceptClient.Send(txtPack.PackToBytes());
    
                    }
                    break;
                default:
                    {
    
                    }
                    break;
            }
        }
    }

     

     

    然後就是消息隊列和php《-》c#間的調用問題

     

    1.嚴格按照p2p模型和pubSub模型的消息隊列-|太阳能万能充,即长沙坎城红毯:

    p2p模型-|-临川晚报: 如果消息接受者的username在clients數組中___金范金素恩,立即發送標-_聂曦,否則存入數據庫作為離線消息_-|杨幂的种子,待該用戶登錄時再從數據庫取出該用戶的離線消息至內存中繼續發送||最新奥特曼电影,直到收到相應類型的ack或baseAck(客戶端的協議比服務器端低)_|-118彩票网是正规大平台吗,從數據庫中徹底移除|_江门长堤风貌街;

    pubSub 模型|__运盛彩票真的假的:不管消息接受在clients數組中有多少個(相同的roomId標記),0到理論上限個-|苏b935nl,立即發送且不需要回執且立即從內存中移除且不存入數據庫

     

    2.由於php和c#程序是2個不同的進程-|保定独立团网,所以涉及到進程間通信|_苏畅古筝,如果這2個程序運行在同一台電腦上-|众赢国际是什么,可行的辦法有-张铁泉为何孤身一人:共享內存||长沙职工大学、本地socket_--开心网001 com登录、管道等等|__火把节是怎么一回事?-_|寒香记?但是實際情況可能我們更希望web程序和消息程序可以不在同一台電腦-||跑马场演员表,因此其他的方法_||众彩软件下载:共享同一個數據庫連接||汤唯在韩国视频、http輪詢

    具體可以根據情況選擇_长沙保险箱,我這裏兩種都有寫|聚美优品网页打不开。

    且我的期望是php每插入一條消息_注册彩金网站,c#馬上推送出去|__门头沟歌华有线电话,那麼c#做數據庫輪詢或者http輪詢其實都還好-_众博棋牌骗了我二十万,我隻用了一個線程做輪詢_|_奎比历斯。

     

    最後今天寫下遊戲端吧||-全国计算机一级考试试题及答案:

    終於可以推各種包了_布鲁金斯基征,開始遊戲包||_阿坝人事、出牌包__-腾格尔歌曲下载、勝利包 DAY1已經描述|_捡钱街,目前在做的||恋狱和之匣: 客戶端牌型校驗以及每一局中的每一輪何時判定-|_高桥亜由美。

    這個遊戲規則就是標準的跑得快_|-掌上武汉APP,也就是拿到黑桃3的玩家第一局第一輪先出牌|_快穿拯救深情男配h全文,這裏還沒做||亿彩彩票能提出来钱么,可以在所有玩家收到開始遊戲包之後做一個簡單的校驗--注册送彩彩金网站。

    過牌直接調用出牌接口|_-038彩票,傳一個空的字符串即可_-盐都网,目前還沒有主動過牌和結束每一輪的邏輯_-|金玫瑰洞下载,做了結束每一局的邏輯-||勇士vs步行者,即判定勝負_金陀。

    最後是幾個測試截圖---动感地带随心聊,玩家id 45 和玩家 id 50玩了一局-|-amd425:

     

About IT165 - 廣告服務 - 隱私聲明 - 版權申明 - 免責條款 - 網站地圖 - 網友投稿 - 聯係方式
本站內容來自於互聯網,僅供用於網絡技術學習,學習中請遵循相關法律法規
国民彩票大象彩票如意彩票v8彩票qq分分彩财神彩票

免责声明: 本站资料及图片来源互联网文章,本网不承担任何由内容信息所引起的争议和法律责任。所有作品版权归原创作者所有,与本站立场无关,如用户分享不慎侵犯了您的权益,请联系我们告知,我们将做删除处理!