mirror of
https://github.com/MirrorNetworking/Mirror.git
synced 2024-11-18 11:00:32 +00:00
feat: Implemented NetworkReaderPool (#1464)
* Implement NetworkReaderPool * Reset Position * Debug logging removed * SetBuffer methods internal * Edited comment
This commit is contained in:
parent
abb570b309
commit
9257112c65
@ -147,19 +147,22 @@ async Task ReceiveRequestAsync(UdpClient udpClient)
|
|||||||
|
|
||||||
UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
|
UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
|
||||||
|
|
||||||
NetworkReader reader = new NetworkReader(udpReceiveResult.Buffer);
|
NetworkReader networkReader = NetworkReaderPool.GetReader(udpReceiveResult.Buffer);
|
||||||
|
|
||||||
long handshake = reader.ReadInt64();
|
long handshake = networkReader.ReadInt64();
|
||||||
if (handshake != secretHandshake)
|
if (handshake != secretHandshake)
|
||||||
{
|
{
|
||||||
// message is not for us
|
// message is not for us
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
throw new ProtocolViolationException("Invalid handshake");
|
throw new ProtocolViolationException("Invalid handshake");
|
||||||
}
|
}
|
||||||
|
|
||||||
Request request = new Request();
|
Request request = new Request();
|
||||||
request.Deserialize(reader);
|
request.Deserialize(networkReader);
|
||||||
|
|
||||||
ProcessClientRequest(request, udpReceiveResult.RemoteEndPoint);
|
ProcessClientRequest(request, udpReceiveResult.RemoteEndPoint);
|
||||||
|
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -330,15 +333,20 @@ async Task ReceiveGameBroadcastAsync(UdpClient udpClient)
|
|||||||
|
|
||||||
UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
|
UdpReceiveResult udpReceiveResult = await udpClient.ReceiveAsync();
|
||||||
|
|
||||||
NetworkReader reader = new NetworkReader(udpReceiveResult.Buffer);
|
NetworkReader networkReader = NetworkReaderPool.GetReader(udpReceiveResult.Buffer);
|
||||||
|
|
||||||
if (reader.ReadInt64() != secretHandshake)
|
if (networkReader.ReadInt64() != secretHandshake)
|
||||||
|
{
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Response response = new Response();
|
Response response = new Response();
|
||||||
response.Deserialize(reader);
|
response.Deserialize(networkReader);
|
||||||
|
|
||||||
ProcessResponse(response, udpReceiveResult.RemoteEndPoint);
|
ProcessResponse(response, udpReceiveResult.RemoteEndPoint);
|
||||||
|
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -451,7 +451,10 @@ void CmdOnAnimationServerMessage(int stateHash, float normalizedTime, int layerI
|
|||||||
if (LogFilter.Debug) Debug.Log("OnAnimationMessage for netId=" + netId);
|
if (LogFilter.Debug) Debug.Log("OnAnimationMessage for netId=" + netId);
|
||||||
|
|
||||||
// handle and broadcast
|
// handle and broadcast
|
||||||
HandleAnimMsg(stateHash, normalizedTime, layerId, new NetworkReader(parameters));
|
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
|
||||||
|
HandleAnimMsg(stateHash, normalizedTime, layerId, networkReader);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
|
|
||||||
RpcOnAnimationClientMessage(stateHash, normalizedTime, layerId, parameters);
|
RpcOnAnimationClientMessage(stateHash, normalizedTime, layerId, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -459,7 +462,10 @@ void CmdOnAnimationServerMessage(int stateHash, float normalizedTime, int layerI
|
|||||||
void CmdOnAnimationParametersServerMessage(byte[] parameters)
|
void CmdOnAnimationParametersServerMessage(byte[] parameters)
|
||||||
{
|
{
|
||||||
// handle and broadcast
|
// handle and broadcast
|
||||||
HandleAnimParamsMsg(new NetworkReader(parameters));
|
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
|
||||||
|
HandleAnimParamsMsg(networkReader);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
|
|
||||||
RpcOnAnimationParametersClientMessage(parameters);
|
RpcOnAnimationParametersClientMessage(parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -486,13 +492,17 @@ void CmdOnAnimationResetTriggerServerMessage(int hash)
|
|||||||
[ClientRpc]
|
[ClientRpc]
|
||||||
void RpcOnAnimationClientMessage(int stateHash, float normalizedTime, int layerId, byte[] parameters)
|
void RpcOnAnimationClientMessage(int stateHash, float normalizedTime, int layerId, byte[] parameters)
|
||||||
{
|
{
|
||||||
HandleAnimMsg(stateHash, normalizedTime, layerId, new NetworkReader(parameters));
|
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
|
||||||
|
HandleAnimMsg(stateHash, normalizedTime, layerId, networkReader);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ClientRpc]
|
[ClientRpc]
|
||||||
void RpcOnAnimationParametersClientMessage(byte[] parameters)
|
void RpcOnAnimationParametersClientMessage(byte[] parameters)
|
||||||
{
|
{
|
||||||
HandleAnimParamsMsg(new NetworkReader(parameters));
|
NetworkReader networkReader = NetworkReaderPool.GetReader(parameters);
|
||||||
|
HandleAnimParamsMsg(networkReader);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
[ClientRpc]
|
[ClientRpc]
|
||||||
|
@ -252,8 +252,9 @@ public override void OnDeserialize(NetworkReader reader, bool initialState)
|
|||||||
void CmdClientToServerSync(byte[] payload)
|
void CmdClientToServerSync(byte[] payload)
|
||||||
{
|
{
|
||||||
// deserialize payload
|
// deserialize payload
|
||||||
NetworkReader reader = new NetworkReader(payload);
|
NetworkReader networkReader = NetworkReaderPool.GetReader(payload);
|
||||||
DeserializeFromReader(reader);
|
DeserializeFromReader(networkReader);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
|
|
||||||
// server-only mode does no interpolation to save computations,
|
// server-only mode does no interpolation to save computations,
|
||||||
// but let's set the position directly
|
// but let's set the position directly
|
||||||
|
@ -488,8 +488,9 @@ static void ApplySpawnPayload(NetworkIdentity identity, SpawnMessage msg)
|
|||||||
// (Count is 0 if there were no components)
|
// (Count is 0 if there were no components)
|
||||||
if (msg.payload.Count > 0)
|
if (msg.payload.Count > 0)
|
||||||
{
|
{
|
||||||
NetworkReader payloadReader = new NetworkReader(msg.payload);
|
NetworkReader payloadReader = NetworkReaderPool.GetReader(msg.payload);
|
||||||
identity.OnUpdateVars(payloadReader, true);
|
identity.OnUpdateVars(payloadReader, true);
|
||||||
|
NetworkReaderPool.Recycle(payloadReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
NetworkIdentity.spawned[msg.netId] = identity;
|
NetworkIdentity.spawned[msg.netId] = identity;
|
||||||
@ -683,7 +684,9 @@ internal static void OnUpdateVarsMessage(UpdateVarsMessage msg)
|
|||||||
|
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity localObject) && localObject != null)
|
||||||
{
|
{
|
||||||
localObject.OnUpdateVars(new NetworkReader(msg.payload), false);
|
NetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload);
|
||||||
|
localObject.OnUpdateVars(networkReader, false);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -697,7 +700,9 @@ internal static void OnRPCMessage(RpcMessage msg)
|
|||||||
|
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
|
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
identity.HandleRPC(msg.componentIndex, msg.functionHash, new NetworkReader(msg.payload));
|
NetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload);
|
||||||
|
identity.HandleRPC(msg.componentIndex, msg.functionHash, networkReader);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,7 +712,9 @@ internal static void OnSyncEventMessage(SyncEventMessage msg)
|
|||||||
|
|
||||||
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
|
if (NetworkIdentity.spawned.TryGetValue(msg.netId, out NetworkIdentity identity))
|
||||||
{
|
{
|
||||||
identity.HandleSyncEvent(msg.componentIndex, msg.functionHash, new NetworkReader(msg.payload));
|
NetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload);
|
||||||
|
identity.HandleSyncEvent(msg.componentIndex, msg.functionHash, networkReader);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -89,16 +89,22 @@ public static byte[] Pack<T>(T message) where T : IMessageBase
|
|||||||
// unpack a message we received
|
// unpack a message we received
|
||||||
public static T Unpack<T>(byte[] data) where T : IMessageBase, new()
|
public static T Unpack<T>(byte[] data) where T : IMessageBase, new()
|
||||||
{
|
{
|
||||||
NetworkReader reader = new NetworkReader(data);
|
NetworkReader networkReader = NetworkReaderPool.GetReader(data);
|
||||||
|
|
||||||
int msgType = GetId<T>();
|
int msgType = GetId<T>();
|
||||||
|
|
||||||
int id = reader.ReadUInt16();
|
int id = networkReader.ReadUInt16();
|
||||||
if (id != msgType)
|
if (id != msgType)
|
||||||
|
{
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
throw new FormatException("Invalid message, could not unpack " + typeof(T).FullName);
|
throw new FormatException("Invalid message, could not unpack " + typeof(T).FullName);
|
||||||
|
}
|
||||||
|
|
||||||
T message = new T();
|
T message = new T();
|
||||||
message.Deserialize(reader);
|
message.Deserialize(networkReader);
|
||||||
|
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -325,7 +325,9 @@ public bool InvokeHandler<T>(T msg, int channelId) where T : IMessageBase
|
|||||||
|
|
||||||
MessagePacker.Pack(msg, writer);
|
MessagePacker.Pack(msg, writer);
|
||||||
ArraySegment<byte> segment = writer.ToArraySegment();
|
ArraySegment<byte> segment = writer.ToArraySegment();
|
||||||
bool result = InvokeHandler(msgType, new NetworkReader(segment), channelId);
|
NetworkReader networkReader = NetworkReaderPool.GetReader(segment);
|
||||||
|
bool result = InvokeHandler(msgType, networkReader, channelId);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
|
|
||||||
// recycle writer and return
|
// recycle writer and return
|
||||||
NetworkWriterPool.Recycle(writer);
|
NetworkWriterPool.Recycle(writer);
|
||||||
@ -345,14 +347,14 @@ public bool InvokeHandler<T>(T msg, int channelId) where T : IMessageBase
|
|||||||
internal void TransportReceive(ArraySegment<byte> buffer, int channelId)
|
internal void TransportReceive(ArraySegment<byte> buffer, int channelId)
|
||||||
{
|
{
|
||||||
// unpack message
|
// unpack message
|
||||||
NetworkReader reader = new NetworkReader(buffer);
|
NetworkReader networkReader = NetworkReaderPool.GetReader(buffer);
|
||||||
if (MessagePacker.UnpackMessage(reader, out int msgType))
|
if (MessagePacker.UnpackMessage(networkReader, out int msgType))
|
||||||
{
|
{
|
||||||
// logging
|
// logging
|
||||||
if (logNetworkMessages) Debug.Log("ConnectionRecv " + this + " msgType:" + msgType + " content:" + BitConverter.ToString(buffer.Array, buffer.Offset, buffer.Count));
|
if (logNetworkMessages) Debug.Log("ConnectionRecv " + this + " msgType:" + msgType + " content:" + BitConverter.ToString(buffer.Array, buffer.Offset, buffer.Count));
|
||||||
|
|
||||||
// try to invoke the handler for that message
|
// try to invoke the handler for that message
|
||||||
if (InvokeHandler(msgType, reader, channelId))
|
if (InvokeHandler(msgType, networkReader, channelId))
|
||||||
{
|
{
|
||||||
lastMessageTime = Time.time;
|
lastMessageTime = Time.time;
|
||||||
}
|
}
|
||||||
@ -362,6 +364,8 @@ internal void TransportReceive(ArraySegment<byte> buffer, int channelId)
|
|||||||
Debug.LogError("Closed connection: " + this + ". Invalid message header.");
|
Debug.LogError("Closed connection: " + this + ". Invalid message header.");
|
||||||
Disconnect();
|
Disconnect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal void AddOwnedObject(NetworkIdentity obj)
|
internal void AddOwnedObject(NetworkIdentity obj)
|
||||||
|
@ -28,7 +28,6 @@ public class NetworkReader
|
|||||||
public int Position;
|
public int Position;
|
||||||
public int Length => buffer.Count;
|
public int Length => buffer.Count;
|
||||||
|
|
||||||
|
|
||||||
public NetworkReader(byte[] bytes)
|
public NetworkReader(byte[] bytes)
|
||||||
{
|
{
|
||||||
buffer = new ArraySegment<byte>(bytes);
|
buffer = new ArraySegment<byte>(bytes);
|
||||||
@ -39,6 +38,20 @@ public NetworkReader(ArraySegment<byte> segment)
|
|||||||
buffer = segment;
|
buffer = segment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetBuffer methods mirror constructor for ReaderPool
|
||||||
|
internal void SetBuffer(byte[] bytes)
|
||||||
|
{
|
||||||
|
buffer = new ArraySegment<byte>(bytes);
|
||||||
|
Position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void SetBuffer(ArraySegment<byte> segment)
|
||||||
|
{
|
||||||
|
buffer = segment;
|
||||||
|
Position = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public byte ReadByte()
|
public byte ReadByte()
|
||||||
{
|
{
|
||||||
if (Position + 1 > buffer.Count)
|
if (Position + 1 > buffer.Count)
|
||||||
|
41
Assets/Mirror/Runtime/NetworkReaderPool.cs
Normal file
41
Assets/Mirror/Runtime/NetworkReaderPool.cs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Mirror
|
||||||
|
{
|
||||||
|
public static class NetworkReaderPool
|
||||||
|
{
|
||||||
|
static readonly Stack<NetworkReader> pool = new Stack<NetworkReader>();
|
||||||
|
|
||||||
|
public static NetworkReader GetReader(byte[] bytes)
|
||||||
|
{
|
||||||
|
if (pool.Count != 0)
|
||||||
|
{
|
||||||
|
NetworkReader reader = pool.Pop();
|
||||||
|
// reset buffer
|
||||||
|
reader.SetBuffer(bytes);
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NetworkReader(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static NetworkReader GetReader(ArraySegment<byte> segment)
|
||||||
|
{
|
||||||
|
if (pool.Count != 0)
|
||||||
|
{
|
||||||
|
NetworkReader reader = pool.Pop();
|
||||||
|
// reset buffer
|
||||||
|
reader.SetBuffer(segment);
|
||||||
|
return reader;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new NetworkReader(segment);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Recycle(NetworkReader reader)
|
||||||
|
{
|
||||||
|
pool.Push(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
11
Assets/Mirror/Runtime/NetworkReaderPool.cs.meta
Normal file
11
Assets/Mirror/Runtime/NetworkReaderPool.cs.meta
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2bacff63613ad634a98f9e4d15d29dbf
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
@ -1016,7 +1016,10 @@ static void OnCommandMessage(NetworkConnection conn, CommandMessage msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (LogFilter.Debug) Debug.Log("OnCommandMessage for netId=" + msg.netId + " conn=" + conn);
|
if (LogFilter.Debug) Debug.Log("OnCommandMessage for netId=" + msg.netId + " conn=" + conn);
|
||||||
identity.HandleCommand(msg.componentIndex, msg.functionHash, new NetworkReader(msg.payload));
|
|
||||||
|
NetworkReader networkReader = NetworkReaderPool.GetReader(msg.payload);
|
||||||
|
identity.HandleCommand(msg.componentIndex, msg.functionHash, networkReader);
|
||||||
|
NetworkReaderPool.Recycle(networkReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static void SpawnObject(GameObject obj, NetworkConnection ownerConnection)
|
internal static void SpawnObject(GameObject obj, NetworkConnection ownerConnection)
|
||||||
|
Loading…
Reference in New Issue
Block a user