/// <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; }
/// <summary> /// データ送信. /// </summary> /// <param name="bytes"></param> /// <param name="offset"></param> /// <param name="length"></param> /// <returns></returns> public int Send(byte[] bytes, int offset, int length) { if (this.IsClosed) { return 0; } int totalBytes = 0; while (totalBytes < length) { int sendBytes = Math.Min( this.Parameter.MaxSegmentSize - Segment.RUDP_HEADER_LEN, length - totalBytes); if (sendBytes <= 0) { throw new ArgumentOutOfRangeException(); } // NOTE // AcknowledgementSegment は受信したあとにハンドリングしないので // AcknowledgementSegment からのシーケンス番号は更新されない. // そのため、Listner - Client でシーケンス番号に齟齬が生じる. // そこで、DataSegment や FinishSegment などを送るときにシーケンス番号をリセットするように // LastInSequenceNumber ではなく、独自に管理しているシーケンス番号を使うようにする. var segment = new DataSegment( this.Counter.NextSequenceNumber(), this.Counter.GetLastInSequenceNumber(), bytes, offset, length); SendAndQueueSegment(segment); totalBytes += length; } return totalBytes; }