private List <SendingPackage> Capsule(byte[] data) { List <SendingPackage> ret = new List <SendingPackage>(); int frameNum = (data.Length + (MTU - DataFrameHeaderLength - PublicFrameHeaderLength) - 1) / (MTU - DataFrameHeaderLength - PublicFrameHeaderLength); ushort currentPosition = 0; for (int i = 0; i < frameNum; i++) { ushort dataLength = (ushort)Math.Min(MTU - DataFrameHeaderLength - PublicFrameHeaderLength, data.Length - currentPosition); byte[] frame = new byte[dataLength + DataFrameHeaderLength]; MemoryStream ms = new MemoryStream(frame); BinaryWriter bw = new BinaryWriter(ms); byte[] lenBytes = BitConverter.GetBytes((ushort)(dataLength + 7)); if (BitConverter.IsLittleEndian) { Array.Reverse(lenBytes); } bw.Write(lenBytes); //0 len bw.Write((byte)4); //2 control byte[] currentSendSeqBytes = BitConverter.GetBytes(_currentSnedSeq); if (BitConverter.IsLittleEndian) { Array.Reverse(currentSendSeqBytes); } bw.Write(currentSendSeqBytes);//3 seqNo byte[] maxPieceBytes = BitConverter.GetBytes((ushort)frameNum); if (BitConverter.IsLittleEndian) { Array.Reverse(maxPieceBytes); } bw.Write(maxPieceBytes); //7 max piece bw.Write(data, currentPosition, dataLength); //9 data bw.Close(); SendingPackage package = new SendingPackage(); package.Content = frame; package.SendingSequenceNo = _currentSnedSeq; package.fastack = 0; package.RetransmissionInterval = RTO; _currentSnedSeq++; currentPosition += dataLength; ret.Add(package); } return(ret); }
//DateTime lastTime; void ProcessRecvQueue(byte[] rawData, int len) { MemoryStream msgStream = new MemoryStream(rawData); BinaryReader reader = new BinaryReader(msgStream); //CRC byte[] checksumBytes = reader.ReadBytes(2); //SESSION byte[] sessionBytes = reader.ReadBytes(4); if (BitConverter.IsLittleEndian) { Array.Reverse(sessionBytes); } UInt32 sessionID = BitConverter.ToUInt32(sessionBytes, 0); //Discard mismatch session package if (sessionID != this.SessionID) { return; } //UNA byte[] unaBytes = reader.ReadBytes(4); if (BitConverter.IsLittleEndian) { Array.Reverse(unaBytes); } UInt32 coUna = BitConverter.ToUInt32(unaBytes, 0); len -= PublicFrameHeaderLength; uint maxAckSeq = 0; while (len > 0) { //len byte[] lenBytes = reader.ReadBytes(2); if (BitConverter.IsLittleEndian) { Array.Reverse(lenBytes); } ushort currentLen = BitConverter.ToUInt16(lenBytes, 0); len -= (currentLen + 2); //Get controll bits byte control = reader.ReadByte(); if (control == (byte)PACKAGE_CATE.DATA) { //this is a data frame byte[] seqDataBytes = reader.ReadBytes(4); if (BitConverter.IsLittleEndian) { Array.Reverse(seqDataBytes); } UInt32 seqData = BitConverter.ToUInt32(seqDataBytes, 0); byte[] maxPieceBytes = reader.ReadBytes(2); if (BitConverter.IsLittleEndian) { Array.Reverse(maxPieceBytes); } ushort maxPiece = BitConverter.ToUInt16(maxPieceBytes, 0); byte[] data = reader.ReadBytes(currentLen - DataFrameHeaderLength + 2); if (seqData > _una && seqData < _una + MaxRecvWindSize) { int recvQueuePos = (int)(seqData - _una - 1); if (_recvQueue[recvQueuePos] == null) { //replace dummy packages RecvingPackage recvPackage = new RecvingPackage(); recvPackage.Data = data; recvPackage.MaxPiece = maxPiece; recvPackage.RecvingSequenceNo = seqData; _recvQueue[recvQueuePos] = recvPackage; //Calculate una int i = 0; for (; i < _recvQueue.Count; i++, _una++) { if (_recvQueue[i] == null) { break; } else { _recvBuffer.Enqueue(_recvQueue[i]); _recvQueue.Add(null); } } _recvQueue.RemoveRange(0, i); } SendAck(seqData); } } else if (control == (byte)PACKAGE_CATE.ACK) //ACK, FIN+ACK { byte[] seqDataBytes = reader.ReadBytes(4); if (BitConverter.IsLittleEndian) { Array.Reverse(seqDataBytes); } UInt32 seqData = BitConverter.ToUInt32(seqDataBytes, 0); //Debug.Log("Recv Ack SeqNo: " + seqData.ToString()); SendingPackage sendPackage = _waitAckList.Find((SendingPackage input) => input.SendingSequenceNo == seqData); if (sendPackage != null) { int newPing = (int)(Clock - sendPackage.FirstSendTimestamp); MobaNetworkManager.Instance.AddPing(newPing); _waitAckList.Remove(sendPackage); if (maxAckSeq < seqData) { maxAckSeq = seqData; } } //Get an ack, set all rto to default RTO = DEFAULT_RTO; for (int i = 0; i < _waitAckList.Count; i++) { _waitAckList[i].RetransmissionInterval = RTO; } } else { Debug.LogError("Receive Illegal Package"); } } //fastack for (int i = 0; i < _waitAckList.Count; i++) { if (_waitAckList[i].SendingSequenceNo < maxAckSeq) { _waitAckList[i].fastack++; } } //process correspondance's una ProcessCoUna(coUna); }
byte[] SendStreamBuffer = new byte[MTU]; // for final frame construction void ProcessSendQueue(float deltaTime) { //Put available packages to waiting dict int readyToSendNum = 0; readyToSendNum = Math.Min(MaxWaitingSendLength - _waitAckList.Count, _sendQueue.Count); for (int i = 0; i < readyToSendNum; i++) { SendingPackage package = _sendQueue.Dequeue(); _sendBuffer.Enqueue(package.Content); package.LastSendTimestamp = Clock; package.FirstSendTimestamp = Clock; _waitAckList.Add(package); } //Re-send un-acked packages //string pendingList = ""; for (int i = 0; i < _waitAckList.Count; i++) { SendingPackage package = _waitAckList[i]; float elapsedTime = Clock - package.LastSendTimestamp; bool needRetransmit = elapsedTime > package.RetransmissionInterval; bool fastack = package.fastack >= 2; if (needRetransmit || fastack) { _sendBuffer.Enqueue(package.Content); package.LastSendTimestamp = Clock; if (fastack) { package.fastack = 0; } else if (needRetransmit) { RTO = (uint)(RTO * 1.5 > MAX_RTO ? MAX_RTO : RTO * 1.5); package.RetransmissionInterval = RTO; } } } int currentPos = PublicFrameHeaderLength; //actually send int iWaitAck = 0; while (_sendBuffer.Count > 0) { byte[] nextSendContent = _sendBuffer.Dequeue(); if (currentPos + nextSendContent.Length > MTU) { for (; iWaitAck < _waitAckList.Count; iWaitAck++) { if (Clock - _waitAckList[iWaitAck].LastSendTimestamp < 0.001f) { continue; } nextSendContent = _waitAckList[iWaitAck].Content; if (currentPos + nextSendContent.Length > MTU) { break; } Array.Copy(nextSendContent, 0, SendStreamBuffer, currentPos, nextSendContent.Length); currentPos += nextSendContent.Length; } Send(SendStreamBuffer, currentPos); currentPos = PublicFrameHeaderLength; } Array.Copy(nextSendContent, 0, SendStreamBuffer, currentPos, nextSendContent.Length); currentPos += nextSendContent.Length; } if (currentPos > PublicFrameHeaderLength) { for (; iWaitAck < _waitAckList.Count; iWaitAck++) { if (Clock - _waitAckList[iWaitAck].LastSendTimestamp < 0.001f) { continue; } byte[] nextSendContent = _waitAckList[iWaitAck].Content; if (currentPos + nextSendContent.Length > MTU) { break; } Array.Copy(nextSendContent, 0, SendStreamBuffer, currentPos, nextSendContent.Length); currentPos += nextSendContent.Length; } Send(SendStreamBuffer, currentPos); } }