using System; namespace XGame.Framework.Network { public class BytesReader : IBytesReader { private enum ReadState { readHead = 0, readBody = 1, closed = 2 } private const int BUFFER_SIZE = ushort.MaxValue; //private const int Length_Heart = 2; //private const int Length_Response = 10;//modify //private const int Length_Push = 6; private ReadState _readState = ReadState.readHead; private int _bytesOffset = 0; private byte[] _recvBytes = new byte[BUFFER_SIZE]; private int _msgLength = 0; private int _headLength = 0; public IMsgReceiver _receiver; public BytesReader(IMsgReceiver receiver) { _receiver = receiver; } public void Read(byte[] bytes, int offset, int length) { while (offset <= length) { if (_readState == ReadState.readHead) { int len = length - offset;//数据长度 if ((_bytesOffset == 0 && len >= 2) || _bytesOffset == 1)//需要知道头部长度的情况 { _headLength = GetHeadLen(bytes[_bytesOffset == 0 ? 1 + offset : 0 + offset]); if (_headLength != NetDefine.HEAD_LENGTH_PUSH && _headLength != NetDefine.HEAD_LENGTH_REQUEST && _headLength != NetDefine.HEAD_LENGTH_HEART) { Log.Error($"[Net] 消息Head长度错误,HeadLength={_headLength}"); Reset(); return; } } //只有知道头部长度才知道是否完整 if (_headLength != 0 && len >= _headLength - _bytesOffset)//说明头部完整 { WriteBytes(bytes, offset, _recvBytes, _bytesOffset, _headLength - _bytesOffset); _readState = ReadState.readBody; offset += _headLength - _bytesOffset; _bytesOffset = _headLength; if (_headLength != NetDefine.HEAD_LENGTH_HEART) { _msgLength = GetMsgLen(_bytesOffset, _recvBytes);//获取消息长度 } if (offset <= length) { //还有数据就接着读 continue; } } else { //能走到这里说明头部不完整 先把byte记下 等下一条 WriteBytes(bytes, offset, _recvBytes, _bytesOffset, len); _bytesOffset += len; } return; } else if (_readState == ReadState.readBody) { int len = length - offset; if (len >= _msgLength + _headLength - _bytesOffset)//body完整 { int realLength = _msgLength + _headLength - _bytesOffset; WriteBytes(bytes, offset, _recvBytes, _bytesOffset, realLength);//全部写入 offset += _msgLength + _headLength - _bytesOffset; _receiver.Receive(_recvBytes, _headLength, _msgLength);//开始解析 Reset(); if (offset < length)//后面接了下一条消息 { continue; } } else { //能走到这里说明body不完整 先把byte记下 等下一条 WriteBytes(bytes, offset, _recvBytes, _bytesOffset, len); _bytesOffset += len; _readState = ReadState.readBody; } return; } } } private int GetMsgLen(int offset, byte[] bytes) { return (bytes[offset - 2] << 8) + bytes[offset - 1]; } private int GetHeadLen(byte _byte) { int type = _byte >> 6; int len = 0; switch ((MsgType)type) { case MsgType.PUSH: len = NetDefine.HEAD_LENGTH_PUSH; break; case MsgType.RESPONSE: len = NetDefine.HEAD_LENGTH_REQUEST; break; case MsgType.HEART_BEAT: len = NetDefine.HEAD_LENGTH_HEART; break; case MsgType.REQUEST: Log.Error($"[Net] MsgType搞错啦!!不是Request! 请确认服务器的地址和端口是否正确!"); break; default: Log.Error($"[Net] MsgType未知的一条消息 type:{type} 请确认服务器的地址和端口是否正确!"); break; } return len; } private void WriteBytes(byte[] source, int sourceOffset, byte[] target, int targetOffset, int length) { Array.Copy(source, sourceOffset, target, targetOffset, length); } public void Reset() { _bytesOffset = 0; _headLength = 0; _msgLength = 0; if (_readState != ReadState.closed) _readState = ReadState.readHead; } } }