csharpc#中的谷歌protobuf消息管理器。专为网络游戏而设计,您应编辑networkmanager类以满足您自己的需求。可以是我们(代码片段)

author author     2023-01-05     378

关键词:

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

using Elecelf.ProtobufToolkits;

namespace Elecelf.ProtobufToolkits

    /// <summary>
    /// A network message manager to 
    /// </summary>
    /// <typeparam name="T">消息的全局类型</typeparam>
    public class NetworkManager<T> where T:ProtoBuf.IExtensible
    
        protected Connection<T> gameServerConnection;
        protected Connection<T> accountServerConnection;

        protected IPEndPoint gameServerEndPoint;
        protected IPEndPoint accountServerEndPoint;

        protected MessageDispatcher<T> gameServerMessageDispatcher = new MessageDispatcher<T>();
        protected MessageDispatcher<T> accountServerMessageDispatcher = new MessageDispatcher<T>();

        public Connection<T> GameServerConnection
        
            get
            
                return gameServerConnection;
            
        

        public Connection<T> AccountServerConnnection
        
            get
            
                return accountServerConnection;
            
        

        public MessageDispatcher<T> GameServerMessageDispatcher
        
            get
            
                return gameServerMessageDispatcher;
            
        

        public MessageDispatcher<T> AccountServerMessageDispatcher
        
            get
            
                return accountServerMessageDispatcher;
            
        

        public IPEndPoint GameServerEndPoint
        
            get
            
                return gameServerEndPoint;
            
            set
            
                gameServerEndPoint = value;
            
        

        public IPEndPoint AccountServerEndPoint
        
            get
            
                return accountServerEndPoint;
            
            set
            
                accountServerEndPoint = value;
            
        
    

using System;
using System.Collections.Generic;

using ProtoBuf;

namespace Elecelf.ProtobufToolkits

    /// <summary>
    /// This class is to manager the events that will be used in a game.
    /// 
    /// Author: Elecelf. Snake Liu
    /// Log:    Apr.1 2014  Create.
    /// </summary>
    public class MessageDispatcher<T> where T : ProtoBuf.IExtensible
    
        public delegate void MessageProcesser(T message);

        protected Dictionary<int, MessageProcesser> routeMap = new Dictionary<int, MessageProcesser>();

        public Dictionary<int, MessageProcesser> RouteMap
        
            get
            
                return routeMap;
            
        

        public void Add(int msgId, MessageProcesser processer)
        
            MessageProcesser hookee;
            if(!routeMap.TryGetValue(msgId, out hookee))
            
                routeMap[msgId] = processer;
            
            else
            
                hookee += processer;
            
        

        public void Remove(int msgId, MessageProcesser processer)
        
            MessageProcesser hookee;
            if(routeMap.TryGetValue(msgId, out hookee))
            
                hookee -= processer;
            
        

        public void Trigger(T msg, int msgId)
        
            MessageProcesser hookee;
            if(routeMap.TryGetValue(msgId, out hookee))
            
                hookee.Invoke(msg);
            
        
    

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;

using ProtoBuf;

namespace Elecelf.ProtobufToolkits

    /// <summary>
    /// Connection类是一个Socket的封装,用于管理服务器连接及序列化/反序列化Protobuf-net消息。
    /// 因该类设计为适用于Unity3D环境,故依据.Net Framework 3.5环境建造。
    /// </summary>
    /// <typeparam name="T">该连接的载体类型。所有收到或发送的Protobuf消息都将依据该类型进行序列化或反序列化。</typeparam>
    public class Connection<T> where T : ProtoBuf.IExtensible
    
        /// <summary>
        /// 完成建立连接工作之后触发此事件。
        /// </summary>
        public event EventHandler OnConnected;

        /// <summary>
        /// 连接因任何原因被断开后触发此事件。
        /// </summary>
        public event EventHandler OnDisconnected;

        /// <summary>
        /// 连接获得服务器消息之后该事件将会被触发。
        /// </summary>
        public event EventHandler<ProtobufEventArgs<T>> OnMessageReceived;

        /// <summary>
        /// 消息发送完成之后该事件将会被触发。
        /// </summary>
        public event EventHandler<ProtobufEventArgs<T>> OnMessageSent;

        protected Socket client/* = new TcpClient()*/;

        protected IPEndPoint endPoint;

        protected ProtocolType protocolType = ProtocolType.Tcp;

        /// <summary>
        /// 网络流对象。
        /// </summary>
        protected NetworkStream stream;

        /// <summary>
        /// 接收消息的缓存
        /// </summary>
        protected byte[] receiveBuff = new byte[1024];

        /// <summary>
        /// 连接的对象。
        /// </summary>
        public IPEndPoint EndPoint
        
            get
            
                return endPoint;
            
        

        /// <summary>
        /// 指示连接关联的套接字是否已连接
        /// </summary>
        public bool Connected
        
            get
            
                return client != null && client.Connected;
            
        

        /// <summary>
        /// 初始化Connection对象。注意,初始化的过程中Connection对象不会连接target参数指定的服务器。
        /// </summary>
        /// <param name="target">指定提供服务的服务器地址及端口号。</param>
        public Connection(IPEndPoint target, ProtocolType protocolType = ProtocolType.Tcp)
        
            client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, protocolType);

            this.protocolType = protocolType;

            endPoint = target;
        

        /// <summary>
        /// 与服务器建立连接。
        /// 连接建立之后将会初始化网络流对象。
        /// </summary>
        public virtual void Connect()
        
            if (client == null)
            
                client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, protocolType);
            

            client.BeginConnect(endPoint.Address, endPoint.Port, OnClientConnected, client);
        

        protected void OnClientConnected(IAsyncResult ar)
        
            stream = new NetworkStream(client);

            if (OnConnected != null)
            
                OnConnected(this, new EventArgs());
            

            StartListen();
        

        #region 监听服务端消息的方法链

        /// <summary>
        /// 开始对protobuf消息的监听,首先监听长度。
        /// </summary>
        protected void StartListen()
        
            byte[] lengthBuff = new byte[2];
            stream.BeginRead(lengthBuff, 0, 2, OnMessageLengthRead, lengthBuff);
        

        /// <summary>
        /// 收到长度之后,依据长度开始监听包体
        /// </summary>
        /// <param name="ar"></param>
        protected void OnMessageLengthRead(IAsyncResult ar)
        
            byte[] lengthBuff = ar.AsyncState as byte[];

            if (BitConverter.IsLittleEndian)
            
                Array.Reverse(lengthBuff);
            

            if (stream == null)
            
                return;
            

            int messageLength = BitConverter.ToUInt16(lengthBuff, 0);
            stream.BeginRead(receiveBuff, 0, messageLength - 2, OnMessageRead, messageLength - 2);
        

        /// <summary>
        /// 收到消息体之后,将消息体反序列化。
        /// </summary>
        /// <param name="ar"></param>
        protected void OnMessageRead(IAsyncResult ar)
        
            using (MemoryStream outputStream = new MemoryStream(receiveBuff))
            
                outputStream.SetLength((int)ar.AsyncState);

                T message = Serializer.Deserialize<T>(outputStream);

                if (OnMessageReceived != null)
                
                    OnMessageReceived(this, new ProtobufEventArgs<T>(message));
                
            

            if (stream == null)
            
                return;
            

            //开启下一个监听
            StartListen();
        

        #endregion

        /// <summary>
        /// 断开服务器连接。
        /// 将导致套接字被回收。
        /// </summary>
        public virtual void Disconnnect()
        
            client.Close();
            client = null;

            stream.Close();
            stream.Dispose();
            stream = null;

            if (OnDisconnected != null)
            
                OnDisconnected(this, new EventArgs());
            
            OnDisconnected = null;
        

        /// <summary>
        /// 发送消息。
        /// </summary>
        /// <param name="message">需要发送的消息。</param>
        public virtual void Send(T message)
        
            using (MemoryStream messageStream = new MemoryStream())
            using (MemoryStream sendStream = new MemoryStream())
            
                Serializer.Serialize<T>(messageStream, message);

                // Length should be send as Big-Endian
                byte[] lengthBuff = BitConverter.GetBytes(Convert.ToUInt16(messageStream.Length + 2));
                if (BitConverter.IsLittleEndian)
                
                    Array.Reverse(lengthBuff);
                

                sendStream.Write(lengthBuff, 0, lengthBuff.Length);
                messageStream.WriteTo(sendStream);
                sendStream.WriteTo(stream);
            

            if (OnMessageSent != null)
                OnMessageSent(this, new ProtobufEventArgs<T>(message));
        
    

    /// <summary>
    /// 需要传递消息内容的事件参数类型。
    /// </summary>
    /// <typeparam name="T">消息载体类型。所有收到或发送的Protobuf消息都将依据该类型进行序列化或反序列化。注意,C# 3.5尚不支持逆变,因此不应继承此类。</typeparam>
    public sealed class ProtobufEventArgs<T> : EventArgs where T : ProtoBuf.IExtensible
    
        private T message;

        /// <summary>
        /// 与该事件相关的消息内容。
        /// </summary>
        public T Message
        
            get
            
                return message;
            
        

        /// <summary>
        /// 使用消息对象初始化示例。
        /// </summary>
        /// <param name="message">相关的消息内容。</param>
        public ProtobufEventArgs(T message)
        
            this.message = message;
        
    

using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;

using ProtoBuf;

namespace Elecelf.ProtobufToolkits

    /// <summary>
    /// Connection类是一个Socket的封装,用于管理服务器连接及序列化/反序列化Protobuf-net消息。
    /// 因该类设计为适用于Unity3D环境,故依据.Net Framework 3.5环境建造。
    /// </summary>
    /// <typeparam name="T">该连接的载体类型。所有收到或发送的Protobuf消息都将依据该类型进行序列化或反序列化。</typeparam>
    public class Connection<T> where T : ProtoBuf.IExtensible
    
        /// <summary>
        /// 完成建立连接工作之后触发此事件。
        /// </summary>
        public event EventHandler OnConnected;

        /// <summary>
        /// 连接因任何原因被断开后触发此事件。
        /// </summary>
        public event EventHandler OnDisconnected;

        /// <summary>
        /// 连接获得服务器消息之后该事件将会被触发。
        /// </summary>
        public event EventHandler<ProtobufEventArgs<T>> OnMessageReceived;

        /// <summary>
        /// 消息发送完成之后该事件将会被触发。
        /// </summary>
        public event EventHandler<ProtobufEventArgs<T>> OnMessageSent;

        protected TcpClient client = new TcpClient();

        protected IPEndPoint endPoint;

        /// <summary>
        /// 网络流对象。
        /// </summary>
        protected NetworkStream stream;

        /// <summary>
        /// 接收消息的缓存
        /// </summary>
        protected byte[] receiveBuff = new byte[1024];

        /// <summary>
        /// 连接的对象。
        /// </summary>
        public IPEndPoint EndPoint
        
            get
            
                return endPoint;
            
        

        /// <summary>
        /// 指示连接关联的套接字是否已连接
        /// </summary>
        public bool Connected
        
            get
            
                return client != null && client.Connected;
            
        

        /// <summary>
        /// 初始化Connection对象。注意,初始化的过程中Connection对象不会连接target参数指定的服务器。
        /// </summary>
        /// <param name="target">指定提供服务的服务器地址及端口号。</param>
        public Connection(IPEndPoint target)
        
            endPoint = target;
        

        /// <summary>
        /// 与服务器建立连接。
        /// 连接建立之后将会初始化网络流对象。
        /// </summary>
        public virtual void Connect()
        
            if (client == null)
            
                client = new TcpClient();
            

            client.BeginConnect(endPoint.Address, endPoint.Port, OnClientConnected, client);
        

        protected void OnClientConnected(IAsyncResult ar)
        
            stream = client.GetStream();

            if (OnConnected != null)
            
                OnConnected(this, new EventArgs());
            

            StartListen();
        

        #region 监听服务端消息的方法链

        /// <summary>
        /// 开始对protobuf消息的监听,首先监听长度。
        /// </summary>
        protected void StartListen()
        
            byte[] lengthBuff = new byte[2];
            stream.BeginRead(lengthBuff, 0, 2, OnMessageLengthRead, lengthBuff);
        

        /// <summary>
        /// 收到长度之后,依据长度开始监听包体
        /// </summary>
        /// <param name="ar"></param>
        protected void OnMessageLengthRead(IAsyncResult ar)
        
            byte[] lengthBuff = ar.AsyncState as byte[];

            if (BitConverter.IsLittleEndian)
            
                Array.Reverse(lengthBuff);
            

            if(stream == null)
            
                return;
            

            int messageLength = BitConverter.ToUInt16(lengthBuff, 0);
            stream.BeginRead(receiveBuff, 0, messageLength - 2, OnMessageRead, messageLength - 2);
        

        /// <summary>
        /// 收到消息体之后,将消息体反序列化。
        /// </summary>
        /// <param name="ar"></param>
        protected void OnMessageRead(IAsyncResult ar)
        
            using (MemoryStream outputStream = new MemoryStream(receiveBuff))
            
                outputStream.SetLength((int)ar.AsyncState);

                T message = Serializer.Deserialize<T>(outputStream);

                if (OnMessageReceived != null)
                
                    OnMessageReceived(this, new ProtobufEventArgs<T>(message));
                
            

            if(stream == null)
            
                return;
            

            //开启下一个监听
            StartListen();
        

        #endregion

        /// <summary>
        /// 断开服务器连接。
        /// 将导致套接字被回收。
        /// </summary>
        public virtual void Disconnnect()
        
            client.Close();
            client = null;

            stream.Close();
            stream.Dispose();
            stream = null;

            if (OnDisconnected != null)
            
                OnDisconnected(this, new EventArgs());
            
            OnDisconnected = null;
        

        /// <summary>
        /// 发送消息。
        /// </summary>
        /// <param name="message">需要发送的消息。</param>
        public virtual void Send(T message)
        
            using (MemoryStream messageStream = new MemoryStream())
            using (MemoryStream sendStream = new MemoryStream())
            
                Serializer.Serialize<T>(messageStream, message);

                // Length should be send as Big-Endian
                byte[] lengthBuff = BitConverter.GetBytes(Convert.ToUInt16(messageStream.Length + 2));
                if (BitConverter.IsLittleEndian)
                
                    Array.Reverse(lengthBuff);
                

                sendStream.Write(lengthBuff, 0, lengthBuff.Length);
                messageStream.WriteTo(sendStream);
                sendStream.WriteTo(stream);
            

            if (OnMessageSent != null)
                OnMessageSent(this, new ProtobufEventArgs<T>(message));
        
    

    /// <summary>
    /// 需要传递消息内容的事件参数类型。
    /// </summary>
    /// <typeparam name="T">消息载体类型。所有收到或发送的Protobuf消息都将依据该类型进行序列化或反序列化。注意,C# 3.5尚不支持逆变,因此不应继承此类。</typeparam>
    public sealed class ProtobufEventArgs<T> : EventArgs where T : ProtoBuf.IExtensible
    
        private T message;

        /// <summary>
        /// 与该事件相关的消息内容。
        /// </summary>
        public T Message
        
            get
            
                return message;
            
        

        /// <summary>
        /// 使用消息对象初始化示例。
        /// </summary>
        /// <param name="message">相关的消息内容。</param>
        public ProtobufEventArgs(T message)
        
            this.message = message;
        
    

Android 中的谷歌云消息服务如何工作?

】Android中的谷歌云消息服务如何工作?【英文标题】:HowGoogleCloudMessagingServiceinAndroidWorks?【发布时间】:2012-06-2809:32:31【问题描述】:我想在我的应用程序中使用GCM服务。我参考了以下链接(AndroidDeveloper:GoogleGCM),但无法在我的E... 查看详情

在 C++ 中更改现有 protobuf 消息的元素

】在C++中更改现有protobuf消息的元素【英文标题】:ChanginganelementofanexistingprotobufmessageinC++【发布时间】:2017-02-1510:53:12【问题描述】:我只是想知道,为什么没有人解决我最近遇到的与googleprotobufs相关的问题,但是经过广泛的谷... 查看详情

带有谷歌时间戳的 Protobuf C++ 消息导致段错误 [重复]

】带有谷歌时间戳的ProtobufC++消息导致段错误[重复]【英文标题】:ProtobufC++messagewithgoogletimestampleadstosegfault[duplicate]【发布时间】:2019-07-1515:10:04【问题描述】:我是使用googleprotobuffers的新手,我创建了一条基本消息:messagemsguint... 查看详情

iOS 中的谷歌分析(不工作)

】iOS中的谷歌分析(不工作)【英文标题】:GoogleAnalyticsiniOS(NotWorking)【发布时间】:2013-09-1613:44:11【问题描述】:我正在尝试实施谷歌分析..你们能帮帮我吗-(void)setGoogleAnalytics//Initializetracker.self.tracker=[[GAIsharedInstance]trackerWithNam... 查看详情

Android 中的谷歌翻译

】Android中的谷歌翻译【英文标题】:GoogleTranslatorinAndroid【发布时间】:2011-02-1216:15:45【问题描述】:我代码遵守http://android-er.blogspot.com/2009/10/multi-language-translate.html它会强制关闭privatevoidshowLang()db.open();cursor=db.getLang();cursor.moveT 查看详情

Wordpress 中的谷歌广告

】Wordpress中的谷歌广告【英文标题】:GoogleadsinWordpress【发布时间】:2013-07-2206:47:26【问题描述】:一年前我在Wordpress中创建了一个新主题。现在我正在根据要求进行更新。我在这个系统中使用了Navayan订阅。我在那个地方(前端... 查看详情

谷歌标签管理器中的 cookiebot 同意模式

】谷歌标签管理器中的cookiebot同意模式【英文标题】:cookiebotingoogletagmanagerwithconsentmode【发布时间】:2021-09-3004:09:30【问题描述】:我正在尝试使用Google跟踪代码管理器和Google的同意模式来实施CookiebotCMP。我按照https://support.cooki... 查看详情

安卓中的谷歌 AppEngine

】安卓中的谷歌AppEngine【英文标题】:GoogleAppEngineinandroid【发布时间】:2014-02-1810:51:08【问题描述】:我是GCM新手,请指导我使用GoogleAppEngine。我想创建一个注册页面,在Google服务器上注册用户的详细信息注册并登录帐户有可能... 查看详情

wordpress 中的谷歌地图

】wordpress中的谷歌地图【英文标题】:Googlemapinwordpress【发布时间】:2015-05-0118:12:35【问题描述】:我想做这样的网站。http://sf.eater.com/maps/the-38-essential-san-francisco-restaurants-january-2015我没有任何Google地图API经验。我在哪里可以获... 查看详情

jquery mobile中的谷歌地图

】jquerymobile中的谷歌地图【英文标题】:googlemapsinjquerymobile【发布时间】:2011-06-0205:25:03【问题描述】:当在jquerymobile中显示谷歌地图时(阅读论坛后),需要如下代码:<divdata-role="page"data-theme="b"class="page-map"style="width:100%;heig... 查看详情

BigQuery 中的谷歌分析实时数据

】BigQuery中的谷歌分析实时数据【英文标题】:GoogleanalyticsrealtimedatainBigQuery【发布时间】:2018-06-0711:12:48【问题描述】:我们启用了continuousexportofGoogleAnalyticsdatatoBigQuery,这意味着我们会得到ga_realtime_sessions_YYYYMMDD全天带有数据... 查看详情

安卓中的谷歌广告词

】安卓中的谷歌广告词【英文标题】:GoogleAdwordsinandroid【发布时间】:2011-02-2810:00:38【问题描述】:您好..我需要在android中做GoogleAdwords。请参阅链接:https://adwords.google.com/o/Targeting/Explorer?_u=1355887856&_c=6610511936&ideaRequestType=... 查看详情

谷歌标签管理器中的adwords转换代码

】谷歌标签管理器中的adwords转换代码【英文标题】:adwordsconversioncodeingoogletagmanager【发布时间】:2014-09-0809:27:33【问题描述】:我有这样的广告词转换代码:<!--GoogleCodeforXXXXRegistrationFormConversionPage--><scripttype="text/javascript"... 查看详情

将谷歌表格加载到仪表板中的谷歌图表

】将谷歌表格加载到仪表板中的谷歌图表【英文标题】:LoadinggooglesheetstogooglechartsinDashboard【发布时间】:2018-03-0521:06:12【问题描述】:我在仪表板上显示Google表格信息时遇到了问题。x和y轴标签显示为Generalxxx。数据来自here。var... 查看详情

sencha 中的谷歌地图处理

】sencha中的谷歌地图处理【英文标题】:Googlemaphandlinginsencha【发布时间】:2013-09-3014:05:59【问题描述】:我已经在基于sencha的应用程序中实现了地图功能。地图正在显示,但无法放大或缩小,也无法向其他方向移动。它在图像... 查看详情

如何从ios中的谷歌帐户注销?

】如何从ios中的谷歌帐户注销?【英文标题】:Howtologoutfromgoogleaccountinios?【发布时间】:2016-11-2915:23:51【问题描述】:在我的应用程序中,我可以选择使用谷歌登录来登录应用程序。登录工作正常。单击注销按钮后,我无法从... 查看详情

Flutter 中的谷歌地图导航

】Flutter中的谷歌地图导航【英文标题】:GoogleMapNavigationinFlutter【发布时间】:2018-12-2214:16:38【问题描述】:我是Flutter新手。我发现Flutter不支持内联地图,只支持静态地图视图。我想构建一个应用程序,我需要在地图上显示行... 查看详情

wordpress中的谷歌分析

Codeindiefunctions.phpeinfügen<?phpadd_action('wp_footer','add_googleanalytics');functionadd_googleanalytics(){?>//PasteyourGoogleAnalyticscodefromStep6here<?php}?> 查看详情