/// <summary> /// out-of-sequenceセグメントがあったことについて返事をする. /// </summary> private void SendExtendAcknowledgement() { lock (this.RecieveQueueLocker) { // 受信したけど out-of-sequence 状態のセグメントが無いのに呼ばれた. if (this.OutSequenceSegmentList.Count == 0) { return; } // out-of-sequenceセグメントのシーケンス番号を集める. int[] ackNumbers = new int[this.OutSequenceSegmentList.Count]; for (int i = 0; i < ackNumbers.Length; i++) { var seqNumber = this.OutSequenceSegmentList.Keys[i]; var segment = this.OutSequenceSegmentList.Values[i]; // シーケンス番号チェック if (segment.SequenceNumber != seqNumber) { throw new ApplicationException(); } ackNumbers[i] = segment.SequenceNumber; // 受信したけど返信していないセグメントをリストから削除. this.UnAckedRecievedSegmentList.Remove(segment); } // out-of-sequenceセグメントリストをリセット. this.OutSequenceSegmentList.Clear(); int lastInSequenceNumber = this.Counter.GetLastInSequenceNumber(); var sendSegment = new ExtendAckSegment( NextSequenceNumber(lastInSequenceNumber), lastInSequenceNumber, ackNumbers); // 送信. SendSegment(sendSegment); } }
/// <summary> /// データをパースして、対応するセグメントを作成する. /// </summary> /// <param name="bytes"></param> /// <param name="offset"></param> /// <param name="length"></param> /// <returns></returns> public static Segment Parse(byte[] bytes, int offset, int length) { Segment ret = null; var flags = bytes[0]; if (CheckFlag(flags, Type.SYN)) { ret = new SynchronousSegment(); } else if (CheckFlag(flags, Type.NUL)) { ret = new NullSegment(); } else if (CheckFlag(flags, Type.EAK)) { ret = new ExtendAckSegment(); } else if (CheckFlag(flags, Type.RST)) { ret = new ResetSegment(); } else if (CheckFlag(flags, Type.FIN)) { ret = new FinishSegment(); } else if (CheckFlag(flags, Type.ACK)) { //var headerSize = bytes[1]; if (length == RUDP_HEADER_LEN) { // ACK ret = new AcknowledgementSegment(); } else { // DAT ret = new DataSegment(); } } if (ret != null) { ret.ReadBytes(bytes, offset, length); } else { throw new ApplicationException(); } return ret; }
private void HandleEAKSegment(ExtendAckSegment segment) { var ackNumbers = segment.AckNumbers; int lastInSequence = segment.GetAcknowledgedNumber(); int lastOutSequence = ackNumbers[ackNumbers.Length - 1]; // 送信したけど応答がないセグメントリストに対象となるものがないか調べる. lock (this.UnAckedSentSegmentList) { List<Segment> willRemoveList = new List<Segment>(); for (int i = 0; i < this.UnAckedSentSegmentList.Count; i++) { var s = this.UnAckedSentSegmentList[i]; if (CompareSequenceNumbers(s.SequenceNumber, lastInSequence) <= 0) { // シーケンス内に入っているので、どこかで応答を受けたはず. willRemoveList.Add(s); continue; } for (int n = 0; n < ackNumbers.Length; n++) { if (CompareSequenceNumbers(s.SequenceNumber, ackNumbers[n]) == 0) { willRemoveList.Add(s); break; } } } foreach (var s in willRemoveList) { this.UnAckedSentSegmentList.Remove(s); } // 残ったのものは再送する. for (int i = 0; i < this.UnAckedSentSegmentList.Count; i++) { var s = this.UnAckedSentSegmentList[i]; if (CompareSequenceNumbers(lastInSequence, s.SequenceNumber) < 0 && CompareSequenceNumbers(lastOutSequence, s.SequenceNumber) > 0) { // 再送. RetransmitSegment(s); } } } }