/// <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> public void Close() { if (this.IsClosed) { return; } switch ((State)this.CurState) { case State.SYN_SENT: // 接続待ちを起こす. this.ConnectEvent.Set(); break; case State.SYN_RECV: case State.ESTABLISHED: // NOTE // AcknowledgementSegment は受信したあとにハンドリングしないので // AcknowledgementSegment からのシーケンス番号は更新されない. // そのため、Listner - Client でシーケンス番号に齟齬が生じる. // そこで、DataSegment や FinishSegment などを送るときにシーケンス番号をリセットするように // LastInSequenceNumber ではなく、独自に管理しているシーケンス番号を使うようにする. var segment = new FinishSegment(this.Counter.NextSequenceNumber()); SendSegment(segment); // TODO // スレッドなどを止める. // 現状は recv がブロッキングされるので、スレッドを止められない. break; default: break; } this.CurState.Store(State.CLOSED); this.VacantUnAckedSentSegListWait.Set(); this.NotEmptyUnAckedSentSegListWait.Set(); this.InSequenceSegWait.Set(); }