private bool ReceiveToPackageBuffer(byte[] buffer , ref int remainCount , ref int readPosition , ArrayPool <byte> .Node receiveBuffer , int targetSize) { int needReadCount = Mathf.Min(targetSize - m_ReceivedPackageCount , remainCount); Array.Copy(buffer , readPosition , receiveBuffer.GetBuffer() , receiveBuffer.GetOffset() + m_ReceivedPackageCount , needReadCount); remainCount -= needReadCount; readPosition += needReadCount; m_ReceivedPackageCount += needReadCount; if (m_ReceivedPackageCount == targetSize) { m_ReceivedPackageCount = 0; return(true); } else { return(false); } }
private void StartSend() { lock (m_SendEventArgs) { if (m_IsSending) { return; } if (m_WaitSendBufferSize == 0) { return; } m_IsSending = true; ArrayPool <byte> .Node swapBuffer = m_SendingBuffer; m_SendingBuffer = m_WaitSendBuffer; m_WaitSendBuffer = swapBuffer; m_SendEventArgs.SetBuffer(m_SendingBuffer.GetBuffer() , m_SendingBuffer.GetOffset() , m_WaitSendBufferSize); m_WaitSendBufferSize = 0; } if (!m_Client.SendAsync(m_SendEventArgs)) { ProcessSend(m_Client, m_SendEventArgs); } }
public unsafe void Send(byte[] data, int offset, int count) { if (!IsConnected()) { MDebug.LogError(LOG_TAG, $"Client({GetName()}) 并未连接,无法发送数据"); return; } byte[] buffer = m_WaitSendBuffer.GetBuffer(); int writePosition = m_WaitSendBuffer.GetOffset() + m_WaitSendBufferSize; fixed(byte *pBuffer = &buffer[writePosition]) { *((TLength *)pBuffer) = PACKAGE_HEADER_SIZE + count; writePosition += PACKAGE_HEADER_SIZE; m_WaitSendBufferSize += PACKAGE_HEADER_SIZE; } Array.Copy(data , offset , m_WaitSendBuffer.GetBuffer() , writePosition , count); m_WaitSendBufferSize += count; StartSend(); }
private void ProcessConnect(object sender, SocketAsyncEventArgs e) { if (e.SocketError == SocketError.Success) { MDebug.Log(LOG_TAG, $"Client({GetName()}) 连接成功"); m_BufferPool = new ArrayPool <byte>(1024 * 512); lock (m_TcpConnectActionLock) { m_TcpConnectData = new TcpConnectData(this, e, ConnectState.Connected); } m_IsSending = false; lock (m_BufferPool) { m_SendEventArgs = new SocketAsyncEventArgs(); m_SendEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(ProcessSend); m_SendingBuffer = m_BufferPool.AllocBuffer(DEFAULT_BUFFER_SIZE); m_WaitSendBuffer = m_BufferPool.AllocBuffer(DEFAULT_BUFFER_SIZE); m_WaitSendBufferSize = 0; m_SendEventArgs.SetBuffer(m_SendingBuffer.GetBuffer(), m_SendingBuffer.GetOffset(), 0); m_ReceiveEventArgs = new SocketAsyncEventArgs(); m_ReceiveEventArgs.Completed += new EventHandler <SocketAsyncEventArgs>(ProcessReceive); m_ReceiveBuffer = m_BufferPool.AllocBuffer(DEFAULT_BUFFER_SIZE); m_ReceiveEventArgs.SetBuffer(m_ReceiveBuffer.GetBuffer(), m_ReceiveBuffer.GetOffset(), m_ReceiveBuffer.GetSize()); m_ReceiveState = ReceiveState.ReceivingPackageLength; m_ReceivedPackageCount = 0; m_ReceiveHeaderBuffer = m_BufferPool.AllocBuffer(PACKAGE_HEADER_SIZE); } lock (m_ReceiveLock) { m_ReceivedPackages = new Queue <ArrayPool <byte> .Node>(); m_ReceivedPackages2 = new BetterList <ArrayPool <byte> .Node>(4); m_ReceivedPackages2._SetCount(m_ReceivedPackages2.Capacity); } StartReceive(); } else { MDebug.LogError(LOG_TAG , $"Client({GetName()}) 连接失败: {e.SocketError.ToString()}\n{e.ConnectByNameError.ToString()}"); lock (m_TcpConnectActionLock) { m_TcpConnectData = new TcpConnectData(this, e, ConnectState.ConnectFailed); } m_Client.Close(); m_Client = null; } }
private void OnReceived(byte[] buffer, int offset, int count) { int remainCount = count; int readPosition = offset; while (remainCount > 0) { switch (m_ReceiveState) { case ReceiveState.ReceivingPackageLength: if (ReceiveToPackageBuffer(buffer , ref remainCount , ref readPosition , m_ReceiveHeaderBuffer , PACKAGE_HEADER_SIZE)) { // SIGN:TLength TLength packageLength = BitConverter.ToInt32(m_ReceiveHeaderBuffer.GetBuffer() , m_ReceiveHeaderBuffer.GetOffset()); lock (m_BufferPool) { m_ReceiveBodyBuffer = m_BufferPool.AllocBuffer(packageLength - PACKAGE_HEADER_SIZE); } m_ReceiveState = ReceiveState.ReceivingPackageBody; } break; case ReceiveState.ReceivingPackageBody: if (ReceiveToPackageBuffer(buffer , ref remainCount , ref readPosition , m_ReceiveBodyBuffer , m_ReceiveBodyBuffer.GetSize())) { lock (m_ReceiveLock) { m_ReceivedPackages.Enqueue(m_ReceiveBodyBuffer); } m_ReceiveBodyBuffer = null; m_ReceiveState = ReceiveState.ReceivingPackageLength; } break; } } }
private void ProcessReceive(object sender, SocketAsyncEventArgs e) { if (e.BytesTransferred > 0 && e.SocketError == SocketError.Success) { MDebug.LogVerbose(LOG_TAG , $"Client({GetName()}) 接收长度: {e.BytesTransferred}"); OnReceived(m_ReceiveBuffer.GetBuffer() , m_ReceiveBuffer.GetOffset() , e.BytesTransferred); StartReceive(); } else { MDebug.LogError(LOG_TAG , $"Client({GetName()}) 接受消息失败: {e.SocketError.ToString()}, 即将断开连接。{e.BytesTransferred}|{e.SocketError}"); Disconnect(e); } }
/// <summary> /// 反序列化 /// <see cref="Serialize"/> /// </summary> public void Deserialize(ArrayPool <RpcValue> rpcValueArrayPool , ObjectPool <RpcValue> rpcValuePool , byte[] buffer , ref int offset , bool enableDeserializeValueType = true) { if (enableDeserializeValueType) { ValueType = (ValueType)buffer[offset]; offset++; } switch (ValueType) { case ValueType.Byte: ByteValue = buffer[offset]; offset++; break; case ValueType.Short: ShortValue = BitConverter.ToInt16(buffer, offset); offset += sizeof(short); break; case ValueType.Int: IntValue = BitConverter.ToInt32(buffer, offset); offset += sizeof(int); break; case ValueType.Long: LongValue = BitConverter.ToInt64(buffer, offset); offset += sizeof(long); break; case ValueType.Float: FloatValue = BitConverter.ToSingle(buffer, offset); offset += sizeof(float); break; case ValueType.Double: DoubleValue = BitConverter.ToDouble(buffer, offset); offset += sizeof(double); break; case ValueType.FixedValueTypeArray: { int elementCount = BitConverter.ToInt32(buffer, offset); offset += sizeof(int); ValueType elementValueType = (ValueType)buffer[offset]; offset++; ArrayValue = rpcValueArrayPool.AllocBuffer(elementCount); int endPoint = ArrayValue.GetOffset() + ArrayValue.GetSize(); RpcValue[] elements = ArrayValue.GetBuffer(); for (int iElement = ArrayValue.GetOffset(); iElement < endPoint; iElement++) { RpcValue iterElement = rpcValuePool.Alloc(); elements[iElement] = iterElement; iterElement.ValueType = elementValueType; iterElement.Deserialize(rpcValueArrayPool , rpcValuePool , buffer , ref offset , false); } } break; case ValueType.VariableValueTypeArray: { int elementCount = BitConverter.ToInt32(buffer, offset); offset += sizeof(int); ArrayValue = rpcValueArrayPool.AllocBuffer(elementCount); int endPoint = ArrayValue.GetOffset() + ArrayValue.GetSize(); RpcValue[] elements = ArrayValue.GetBuffer(); for (int iElement = ArrayValue.GetOffset(); iElement < endPoint; iElement++) { RpcValue iterElement = rpcValuePool.Alloc(); elements[iElement] = iterElement; iterElement.Deserialize(rpcValueArrayPool , rpcValuePool , buffer , ref offset); } } break; default: throw new Exception("Not support ValueType: " + ValueType); } }
/// <summary> /// 序列化 /// </summary> /// <param name="buffer">目标Buffer</param> /// <param name="offset">写入位置</param> /// <param name="enableSerializeValueType"> /// 是否序列化<see cref="ValueType"/> /// 需要这个开关是因为序列化<see cref="ValueType.FixedValueTypeArray"/>时,不需要序列化数组中每个元素的<see cref="ValueType"/> /// </param> public void Serialize(byte[] buffer , ref int offset , bool enableSerializeValueType = true) { if (enableSerializeValueType) { MBitConverter.WriteTo(buffer, ref offset, (byte)ValueType); } switch (ValueType) { case ValueType.Byte: MBitConverter.WriteTo(buffer, ref offset, ByteValue); break; case ValueType.Short: MBitConverter.WriteTo(buffer, ref offset, ShortValue); break; case ValueType.Int: MBitConverter.WriteTo(buffer, ref offset, IntValue); break; case ValueType.Long: MBitConverter.WriteTo(buffer, ref offset, LongValue); break; case ValueType.Float: MBitConverter.WriteTo(buffer, ref offset, FloatValue); break; case ValueType.Double: MBitConverter.WriteTo(buffer, ref offset, DoubleValue); break; case ValueType.FixedValueTypeArray: { int elementCount = ArrayValue.GetSize(); MBitConverter.WriteTo(buffer, ref offset, elementCount); MDebug.Assert(elementCount > 0 , "Rpc" , "elementCount > 0"); int startPoint = ArrayValue.GetOffset(); int endPoint = startPoint + elementCount; RpcValue[] elements = ArrayValue.GetBuffer(); ValueType elementValueType = elements[startPoint].ValueType; MBitConverter.WriteTo(buffer, ref offset, (byte)elementValueType); for (int iElement = startPoint; iElement < endPoint; iElement++) { RpcValue iterElement = elements[iElement]; #if GF_DEBUG MDebug.Assert(iterElement.ValueType == elementValueType , "Rpc" , "iterElement.ValueType == elementValueType"); #endif iterElement.Serialize(buffer, ref offset, false); } } break; case ValueType.VariableValueTypeArray: { int elementCount = ArrayValue.GetSize(); MBitConverter.WriteTo(buffer, ref offset, elementCount); MDebug.Assert(elementCount > 0 , "Rpc" , "elementCount > 0"); int startPoint = ArrayValue.GetOffset(); int endPoint = startPoint + elementCount; RpcValue[] elements = ArrayValue.GetBuffer(); for (int iElement = startPoint; iElement < endPoint; iElement++) { RpcValue iterElement = elements[iElement]; iterElement.Serialize(buffer, ref offset); } } break; default: throw new Exception("Not support ValueType: " + ValueType); } }