您最多选择25个主题
主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
108 行
3.3 KiB
108 行
3.3 KiB
using System;
|
|
using System.Net.Sockets;
|
|
using UnityEngine;
|
|
using Unity.Collections;
|
|
using Unity.Collections.LowLevel.Unsafe;
|
|
|
|
/// <summary>
|
|
/// Sends and receives data using a fixed size byte[] buffer. Because the
|
|
/// buffer is reused, no additional GC allocations are made after construction.
|
|
/// </summary>
|
|
public struct NetworkBuffer
|
|
{
|
|
byte[] m_Buffer;
|
|
|
|
public NetworkBuffer(int bufferSize)
|
|
{
|
|
m_Buffer = new byte[bufferSize];
|
|
}
|
|
|
|
public byte[] buffer => m_Buffer;
|
|
|
|
public int bufferSize => (m_Buffer == null) ? 0 : m_Buffer.Length;
|
|
|
|
public int Read(NetworkStream stream, int offset, int size)
|
|
{
|
|
ValidateAndThrow(stream);
|
|
|
|
if (offset < 0)
|
|
throw new ArgumentOutOfRangeException(nameof(offset), offset, $"{nameof(offset)} must be greater than or equal to zero.");
|
|
|
|
if (size < 0)
|
|
throw new ArgumentOutOfRangeException(nameof(size), size, $"{nameof(size)} must be greater than or equal to zero.");
|
|
|
|
if (offset + size > m_Buffer.Length)
|
|
throw new InvalidOperationException($"Reading {size} bytes starting at offset {offset} would read past the end of the buffer (buffer length = {m_Buffer.Length}).");
|
|
|
|
int bytesRemaining = size;
|
|
while (bytesRemaining > 0)
|
|
{
|
|
int bytesRead = stream.Read(m_Buffer, offset, bytesRemaining);
|
|
CollaborationNetworkingIndicator.NotifyIncomingDataReceived();
|
|
offset += bytesRead;
|
|
bytesRemaining -= bytesRead;
|
|
}
|
|
|
|
return size;
|
|
}
|
|
|
|
public void Send(NetworkStream stream, int offset, int size)
|
|
{
|
|
ValidateAndThrow(stream);
|
|
|
|
if (offset + size > m_Buffer.Length)
|
|
throw new InvalidOperationException($"Writing {size} bytes starting at offset {offset} would write past the end of the buffer (buffer length = {m_Buffer.Length}).");
|
|
|
|
try
|
|
{
|
|
stream.Write(m_Buffer, offset, size);
|
|
CollaborationNetworkingIndicator.NotifyOutgoingDataSent();
|
|
}
|
|
catch (SocketException socketException)
|
|
{
|
|
Logger.Log($"Socket exception: {socketException}");
|
|
}
|
|
}
|
|
|
|
public unsafe void Send(NetworkStream stream, NativeSlice<byte> bytes)
|
|
{
|
|
ValidateAndThrow(stream);
|
|
|
|
var basePtr = new IntPtr(bytes.GetUnsafeReadOnlyPtr());
|
|
int bytesRemaining = bytes.Length;
|
|
int offset = 0;
|
|
|
|
while (bytesRemaining > 0)
|
|
{
|
|
// Memcpy next chunk into destinationBuffer
|
|
int size = Mathf.Min(m_Buffer.Length, bytesRemaining);
|
|
fixed(byte* dst = m_Buffer)
|
|
{
|
|
var src = basePtr + offset;
|
|
UnsafeUtility.MemCpy(dst, (void*)src, size);
|
|
}
|
|
|
|
bytesRemaining -= size;
|
|
offset += size;
|
|
|
|
Send(stream, 0, size);
|
|
}
|
|
}
|
|
|
|
public void Send<T>(NetworkStream stream, T message) where T : struct, IMessage
|
|
{
|
|
ValidateAndThrow(stream);
|
|
|
|
int size = message.EncodeTo(m_Buffer);
|
|
Send(stream, 0, size);
|
|
}
|
|
|
|
void ValidateAndThrow(NetworkStream stream)
|
|
{
|
|
if (stream == null)
|
|
throw new ArgumentNullException(nameof(stream));
|
|
|
|
if (m_Buffer == null)
|
|
throw new InvalidOperationException($"{nameof(NetworkBuffer)} has not been initialized.");
|
|
}
|
|
}
|