重庆快速网站推广,在线考试网站模板,适合初学者做的网页,网站logo源码lidgren有几个优点#xff1a;分channel#xff0c;每个channel都有单独的消息队列#xff0c;不互相影响。每个消息可以单独选择使用可靠/不可靠传输。支持内网穿透自带加密算法。前端Unity#xff1a;先贴一张前端使用的网络框架图#xff1a;Lidgren的Github地址#… lidgren有几个优点分channel每个channel都有单独的消息队列不互相影响。每个消息可以单独选择使用可靠/不可靠传输。支持内网穿透自带加密算法。 前端Unity先贴一张前端使用的网络框架图 Lidgren的Github地址https://github.com/lidgren/lidgren-network-gen3在Player Setting中要加上宏定义UNITY连接NetPeerConfiguration config new NetPeerConfiguration (NetworkConfig.CONNECTION_IDENTIFIER);//参数是一个字符串标识前后端一致。config.EnableMessageType (NetIncomingMessageType.ConnectionLatencyUpdated);//监听收发心跳的事件。m_connection new NetClient (config);m_connection.Start ();m_receiveCallBack new SendOrPostCallback (OnReceiveMessage);//收发消息的回调m_connection.RegisterReceivedCallback(m_receiveCallBack, new SynchronizationContext()); m_connection.Connect (ip, port); 断开连接m_connection.Disconnect ();
m_connection.UnregisterReceivedCallback (m_receiveCallBack); 发送消息NetOutgoingMessage nm connection.CreateMessage (bytesLength);
nm.Write (bytes, 0, bytesLength);
m_connection.SendMessage (nm, (NetDeliveryMethod)channelType, channel); NetDeliveryMethod有以下几类UnReliable不可靠传输顺序和丢包都不能保证UnReliableSequence不可靠传输按顺序接收 旧包直接丢弃ReliableUnOrdered可靠传输不保证顺序但是不会丢包ReliableSequence可靠传输和UnReliableSequence但是有一个缓冲窗口超过缓冲范围的包会丢弃ReliableOrdered可靠传输不丢包保证顺序 接收消息void OnReceiveMessage(object state) { NetIncomingMessage im; while ((im m_connection.ReadMessage()) ! null) { switch (im.MessageType) { case NetIncomingMessageType.ErrorMessage: case NetIncomingMessageType.WarningMessage: //处理错误和警告 break; case NetIncomingMessageType.DebugMessage: //debug输出 break; case NetIncomingMessageType.VerboseDebugMessage: //消息重发或丢弃的debug消息 break; case NetIncomingMessageType.StatusChanged: //网络状态变化 break; case NetIncomingMessageType.Data: //收到消息处理ReceiveMessages (im.ReadBytes (im.LengthBytes), im.LengthBytes); break; case NetIncomingMessageType.ConnectionLatencyUpdated: //Lidgren收发心跳包后回调 break; default: break; } connection.Recycle(im); } }后端DotNetty后端是参照TCPServerSocketChannel和TCPSocketChannel改的。Server的UnSafe可以写一个空类class LidgrenUdpServerUnsafeChannel : AbstractUnsafe { public LidgrenUdpServerUnsafeChannel(AbstractChannel channel) : base(channel) { } public override Task ConnectAsync(EndPoint remoteAddress, EndPoint localAddress) { return null; } public void FinishRead() { } }再实现一个ServerChannelpublic class LidgrenUdpServerChannel : AbstractChannel, IServerChannel { public const string CONNECTION_IDENTIFIER xxxxx; NetServer m_server; LidgrenChannelConfig m_config; public NetServer Server { get { return m_server; } } DictionaryNetConnection, LidgrenUdpChannel m_connectionList new DictionaryNetConnection, LidgrenUdpChannel(); public LidgrenUdpServerChannel() : base(null) { m_config new LidgrenChannelConfig(CONNECTION_IDENTIFIER); m_server new NetServer(m_config.Config); } protected override IChannelUnsafe NewUnsafe() { return new LidgrenUdpServerUnsafeChannel(this); } ... }开始监听protected override void DoBind(EndPoint localAddress) { m_config.Config.Port ((IPEndPoint)localAddress).Port; this.m_server.Start(); this.m_server.RegisterReceivedCallback(new System.Threading.SendOrPostCallback(OnRead), new System.Threading.SynchronizationContext()); } OnRead类似客户端的OnReceiveMessage建立/断开连接case NetIncomingMessageType.StatusChanged: NetConnectionStatus ns (NetConnectionStatus)im.ReadByte(); if (ns NetConnectionStatus.Connected) { LidgrenUdpChannel udpChannel new LidgrenUdpChannel(this, im.SenderConnection); Pipeline.FireChannelRead(udpChannel); lock (((System.Collections.ICollection)m_connectionList).SyncRoot) { m_connectionList.Add(im.SenderConnection, udpChannel); } } if (ns NetConnectionStatus.Disconnected) { lock (((System.Collections.ICollection)m_connectionList).SyncRoot) { LidgrenUdpChannel channel null; if (m_connectionList.TryGetValue(im.SenderConnection, out channel)) { channel.Pipeline.FireChannelInactive(); m_connectionList.Remove(im.SenderConnection); } } } break;接收消息case NetIncomingMessageType.Data: LidgrenUdpChannel readChannel null; lock (((System.Collections.ICollection)m_connectionList).SyncRoot) { if (m_connectionList.TryGetValue(im.SenderConnection, out readChannel)) { readChannel.ReadBytes(im.ReadBytes(im.LengthBytes)); } } break;对于每一个客户端都有一个单独的channel public class LidgrenUdpChannel : AbstractChannel发送消息protected int DoWriteBytes(IByteBuffer buf) { if (!buf.HasArray) { throw new NotImplementedException(Only IByteBuffer implementations backed by array are supported.); } int sent buf.ReadableBytes; NetOutgoingMessage msg m_parentChannel.Server.CreateMessage(); msg.Write(buf.Array, buf.ArrayOffset buf.ReaderIndex, buf.ReadableBytes); m_connection.SendMessage(msg, NetDeliveryMethod.ReliableOrdered, 0); if (sent 0) { buf.SetReaderIndex(buf.ReaderIndex sent); } return sent; } protected override void DoWrite(ChannelOutboundBuffer input) { while (true) { object msg input.Current; if (msg null) { // Wrote all messages. break; } if (msg is IByteBuffer) { IByteBuffer buf (IByteBuffer)msg; int readableBytes buf.ReadableBytes; if (readableBytes 0) { input.Remove(); continue; } bool done false; long flushedAmount 0; int localFlushedAmount this.DoWriteBytes(buf); flushedAmount localFlushedAmount; if (!buf.IsReadable()) { done true; } input.Progress(flushedAmount); buf.Release(); if (done) { input.Remove(); } else { throw new InvalidOperationException(); } } else { // Should not reach here. throw new InvalidOperationException(); } } }接收消息 public void ReadBytes(byte[] bytes){ if (!Open) return; this.EventLoop.Execute(() { ((LidgrenUdpUnsafe)Unsafe).ReadBytes(bytes); });}UnSafe中public void FinishRead() { channel.Read(); } public void ReadBytes(byte[] bytes) { IByteBufferAllocator allocator channel.Allocator; IRecvByteBufAllocatorHandle allocHandle RecvBufAllocHandle; IByteBuffer byteBuf allocHandle.Allocate(allocator); byteBuf.WriteBytes(bytes); channel.Pipeline.FireChannelRead(byteBuf); channel.Pipeline.FireChannelReadComplete(); allocHandle.ReadComplete(); }Lidgren不支持ipv6修改方法参照这里https://github.com/SteveProXNA/UnityLidgrenIPv6/tree/master/IPv6原文http://www.cnblogs.com/drashnane/p/6415973.html.NET社区新闻深度好文欢迎访问公众号文章汇总 http://www.csharpkit.com