private CodedOutputStream( ByteBuf output, byte[] buffer) { this.output = output; this.buffer = buffer; position = 0; limit = buffer.Length; }
/** * 分帧逻辑 * **/ public ByteBuf TranslateFrame(ByteBuf src) { while (src.ReadableBytes() > 0) { switch (status) { case 0: h = src.ReadByte(); status = 1; break; case 1: l = src.ReadByte(); len = (short)(((h << 8)&0x0000ff00) | (l)); frame = new ByteBuf(len + 2); frame.WriteShort(len); status = 2; break; case 2: int min=frame.WritableBytes(); min=src.ReadableBytes()<min?src.ReadableBytes():min; if(min>0) { frame.WriteBytes(src,min); } if (frame.WritableBytes() <= 0) { status = 0; return frame; } break; } } return null; }
/** * 写入一个varint32 */ public static ByteBuf WriteVarint32(ByteBuf tar, int v) { int len = CodedOutputStream.computeRawVarint32Size(v); CodedOutputStream headerOut = CodedOutputStream.newInstance(tar, len); headerOut.writeRawVarint32(v); headerOut.flush(); return tar; }
public override void OnMessage(USocket us,ByteBuf bb) { Console.WriteLine ("收到数据:"); bb.ReaderIndex (2); string s=bb.ReadUTF8 (); Console.WriteLine (s); bb.ReaderIndex (0); us.Send (bb);//原样返回给服务器,服务器是一个echo,也会原样返回 }
/** * 拷贝 **/ public ByteBuf Copy() { ByteBuf item = new ByteBuf(len); Array.Copy (this.data, item.data, len); item.readerIndex = readerIndex; item.writerIndex = writerIndex; item.markReader = markReader; item.markWriter = markWriter; return item; }
public override void OnMessage(USocket us,ByteBuf bb) { Console.WriteLine ("收到数据:"); bb.ReaderIndex (us.getProtocal().HeaderLen()); int cmd = bb.ReadShort(); MemoryStream stream = new MemoryStream(bb.GetRaw(),bb.ReaderIndex(),bb.ReadableBytes()); AuthResponse response= ProtoBuf.Serializer.Deserialize<AuthResponse>(stream); Console.WriteLine (response.pid); Console.WriteLine(response.info); Console.WriteLine(response.success); }
/** * 分帧逻辑 * **/ public ByteBuf TranslateFrame(ByteBuf src) { while (src.ReadableBytes() > 0) { switch (status) { case STATUS_HEADER: for (; index < header.Length; index++) { if (!(src.ReadableBytes() > 0)) { break; } header[index] = (sbyte)src.ReadByte(); if (header[index] >= 0) { int length = 0; length = CodedInputStream.newInstance(header, 0, index + 1).readRawVarint32(); if (length < 0) { return null; } len = length; headerLen = CodedOutputStream.computeRawVarint32Size(len); Console.WriteLine (":"+len+":"+headerLen); incompleteframe = new ByteBuf(len + headerLen); CodedOutputStream headerOut = CodedOutputStream.newInstance(incompleteframe, headerLen); headerOut.writeRawVarint32(len); headerOut.flush(); status = STATUS_CONTENT; break; } } break; case STATUS_CONTENT: int l = Math.Min(src.ReadableBytes(), incompleteframe.WritableBytes()); if (l > 0) { incompleteframe.WriteBytes(src, l); } if (incompleteframe.WritableBytes() <= 0) { status = STATUS_HEADER; index = 0; return incompleteframe; } break; } } return null; }
public override void OnMessage(USocket us,ByteBuf bb) { Console.WriteLine ("收到数据:"); bb.ReaderIndex (us.getProtocal().HeaderLen()); int cmd = bb.ReadShort(); Type t=null; MemoryStream stream = new MemoryStream(bb.GetRaw(),bb.ReaderIndex(),bb.ReadableBytes()); object response=ProtoBuf.Serializer.NonGeneric.Deserialize(t,stream); /** Console.WriteLine (response.pid); Console.WriteLine(response.info); Console.WriteLine(response.success); */ }
/** * 封包 */ public override void End() { if (!this.end) { ByteBuf bb = payload; int reader = bb.ReaderIndex(); int writer = bb.WriterIndex(); int l = writer - reader;//数据长度 ByteBuf tar = new ByteBuf(l + 5); WriteVarint32(tar, l); tar.WriteBytes(bb); payload = tar; this.end = true; } }
public static void Main(string[] args) { KcpClient client = new TestKcp(2223); client.NoDelay(1, 10, 2, 1); //fast client.WndSize(64, 64); client.Timeout(10 * 1000); client.SetMtu(1000); client.Connect("119.29.153.92", 2222); client.Start(); Thread.Sleep(2000); String s = "hi,heoll world! 你好啊!!"; //for (int i = 0; i < 2; i++) //{ // s = s + s; //} ByteBuf bb = new ByteBuf(System.Text.Encoding.UTF8.GetBytes(s)); Console.WriteLine(bb.ReadableBytes()); client.Send(bb); Console.Read(); }
/** * 分帧逻辑 * **/ public ByteBuf TranslateFrame(ByteBuf src) { while (src.ReadableBytes() > 0) { switch (status) { case 0: h = src.ReadByte(); status = 1; break; case 1: l = src.ReadByte(); len = (short)(((h << 8) & 0x0000ff00) | (l)); frame = new ByteBuf(len + 2); frame.WriteShort(len); status = 2; break; case 2: int min = frame.WritableBytes(); min = src.ReadableBytes() < min?src.ReadableBytes() : min; if (min > 0) { frame.WriteBytes(src, min); } if (frame.WritableBytes() <= 0) { status = 0; return(frame); } break; } } return(null); }
public override void output(ByteBuf msg, Kcp kcp, Object user) { this.client.Send(msg.GetRaw(), msg.ReadableBytes()); }
/** * 写入一部分字节 **/ public ByteBuf WriteBytes(ByteBuf src ,int len) { if (len > 0) { Capacity(writerIndex + len); Array.Copy (src.data, src.readerIndex, data, writerIndex, len); writerIndex += len; src.readerIndex += len; } return this; }
/** * flush pending data */ private void Flush() { int cur = current; int change = 0; int lost = 0; if (updated == 0) { return; } Segment seg = new Segment(0); seg.conv = conv; seg.cmd = IKCP_CMD_ACK; seg.wnd = wnd_unused(); seg.una = rcv_nxt; // flush acknowledges int c = acklist.Count / 2; for (int i = 0; i < c; i++) { if (buffer.ReadableBytes() + IKCP_OVERHEAD > mtu) { this.output.output(buffer, this, user); buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); } seg.sn = acklist[i * 2 + 0]; seg.ts = acklist[i * 2 + 1]; seg.Encode(buffer); } acklist.Clear(); // probe window size (if remote window size equals zero) if (rmt_wnd == 0) { if (probe_wait == 0) { probe_wait = IKCP_PROBE_INIT; ts_probe = current + probe_wait; } else if (_itimediff(current, ts_probe) >= 0) { if (probe_wait < IKCP_PROBE_INIT) { probe_wait = IKCP_PROBE_INIT; } probe_wait += probe_wait / 2; if (probe_wait > IKCP_PROBE_LIMIT) { probe_wait = IKCP_PROBE_LIMIT; } ts_probe = current + probe_wait; probe |= IKCP_ASK_SEND; } } else { ts_probe = 0; probe_wait = 0; } // flush window probing commands if ((probe & IKCP_ASK_SEND) != 0) { seg.cmd = IKCP_CMD_WASK; if (buffer.ReadableBytes() + IKCP_OVERHEAD > mtu) { this.output.output(buffer, this, user); buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); } seg.Encode(buffer); } // flush window probing commands if ((probe & IKCP_ASK_TELL) != 0) { seg.cmd = IKCP_CMD_WINS; if (buffer.ReadableBytes() + IKCP_OVERHEAD > mtu) { this.output.output(buffer, this, user); buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); } seg.Encode(buffer); } probe = 0; // calculate window size int cwnd_temp = Math.Min(snd_wnd, rmt_wnd); if (nocwnd == 0) { cwnd_temp = Math.Min(cwnd, cwnd_temp); } // move data from snd_queue to snd_buf c = 0; for (int i = 0; i < snd_queue.Count; i++) { Segment item = snd_queue[i]; if (_itimediff(snd_nxt, snd_una + cwnd_temp) >= 0) { break; } Segment newseg = item; newseg.conv = conv; newseg.cmd = IKCP_CMD_PUSH; newseg.wnd = seg.wnd; newseg.ts = cur; newseg.sn = snd_nxt++; newseg.una = rcv_nxt; newseg.resendts = cur; newseg.rto = rx_rto; newseg.fastack = 0; newseg.xmit = 0; snd_buf.Add(newseg); c++; } if (c > 0) { snd_queue.RemoveRange(0, c); } // calculate resent int resent = (fastresend > 0) ? fastresend : int.MaxValue; int rtomin = (nodelay == 0) ? (rx_rto >> 3) : 0; // flush data segments for (int i = 0; i < snd_buf.Count; i++) { Segment segment = snd_buf[i]; bool needsend = false; if (segment.xmit == 0) { needsend = true; segment.xmit++; segment.rto = rx_rto; segment.resendts = cur + segment.rto + rtomin; } else if (_itimediff(cur, segment.resendts) >= 0) { needsend = true; segment.xmit++; xmit++; if (nodelay == 0) { segment.rto += rx_rto; } else { segment.rto += rx_rto / 2; } segment.resendts = cur + segment.rto; lost = 1; } else if (segment.fastack >= resent) { needsend = true; segment.xmit++; segment.fastack = 0; segment.resendts = cur + segment.rto; change++; } if (needsend) { segment.ts = cur; segment.wnd = seg.wnd; segment.una = rcv_nxt; int need = IKCP_OVERHEAD + segment.data.ReadableBytes(); if (buffer.ReadableBytes() + need > mtu) { this.output.output(buffer, this, user); buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); } segment.Encode(buffer); if (segment.data.ReadableBytes() > 0) { buffer.WriteBytes(segment.data.Duplicate()); } if (segment.xmit >= dead_link) { state = -1; } } } // flash remain segments if (buffer.ReadableBytes() > 0) { this.output.output(buffer, this, user); buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); } // update ssthresh if (change != 0) { int inflight = snd_nxt - snd_una; ssthresh = inflight / 2; if (ssthresh < IKCP_THRESH_MIN) { ssthresh = IKCP_THRESH_MIN; } cwnd = ssthresh + resent; incr = cwnd * mss; } if (lost != 0) { ssthresh = cwnd / 2; if (ssthresh < IKCP_THRESH_MIN) { ssthresh = IKCP_THRESH_MIN; } cwnd = 1; incr = mss; } if (cwnd < 1) { cwnd = 1; incr = mss; } }
abstract public void OnMessage(USocket us, ByteBuf bb);
public Frame (int len) { this.payload = new ByteBuf (len); payload.WriteShort(0); }
/** * user/upper level recv: returns size, returns below zero for EAGAIN * * @param buffer * @return */ public int Receive(ByteBuf buffer) { if (rcv_queue.Count <= 0) { return(-1); } int peekSize = PeekSize(); if (peekSize < 0) { return(-2); } bool recover = rcv_queue.Count >= rcv_wnd; // merge fragment. int c = 0; int len = 0; for (int i = 0; i < rcv_queue.Count; i++) { Segment seg = rcv_queue[i]; len += seg.data.ReadableBytes(); buffer.WriteBytes(seg.data); c++; if (seg.frg == 0) { break; } } if (c > 0) { rcv_queue.RemoveRange(0, c); } if (len != peekSize) { throw new Exception("数据异常."); } // move available data from rcv_buf -> rcv_queue c = 0; for (int i = 0; i < rcv_buf.Count; i++) { Segment seg = rcv_buf[i]; if (seg.sn == rcv_nxt && rcv_queue.Count < rcv_wnd) { rcv_queue.Add(seg); rcv_nxt++; c++; } else { break; } } if (c > 0) { rcv_buf.RemoveRange(0, c); } // fast recover if (rcv_queue.Count < rcv_wnd && recover) { // ready to send back IKCP_CMD_WINS in ikcp_flush // tell remote my window size probe |= IKCP_ASK_TELL; } return(len); }
/** * 构造 */ public USocket(SocketListner listner, Protocal protocal) { this.listner = listner; this.protocal = protocal; buf = new ByteBuf(4096); }
/** * 构造(但不完善,需要设置监听器和协议解析器) */ public USocket() { buf = new ByteBuf(4096); }
/** * 处理收到的消息 */ protected void HandleReceive(ByteBuf bb) { KcpListener.handleReceive(bb); }
abstract public void OnMessage(USocket us,ByteBuf bb);
abstract public void output(ByteBuf msg, Kcp kcp, Object user);
protected override void HandleReceive(ByteBuf bb) { string content = System.Text.Encoding.UTF8.GetString(bb.GetRaw()); Console.WriteLine("msg:" + content); }
/** * Create a new {@code CodedOutputStream} wrapping the given * {@code OutputStream} with a given buffer size. * * @param output * @param bufferSize * @return */ public static CodedOutputStream newInstance(ByteBuf output, int bufferSize) { return(new CodedOutputStream(output, new byte[bufferSize])); }
/** * 构造(但不完善,需要设置监听器和协议解析器F) */ public USocket() { buf=new ByteBuf(4096); }
abstract public void output(ByteBuf msg, Kcp kcp);
/** *发送 */ public IAsyncResult Send(ByteBuf buf) { try { byte[] msg=buf.GetRaw(); IAsyncResult asyncSend = clientSocket.BeginSend (msg,buf.ReaderIndex(),buf.ReadableBytes(),SocketFlags.None,sended,buf); return asyncSend; } catch { return null; } }
public Segment(int size) { this.data = new ByteBuf(size); }
/** * flush pending data */ private void flush() { int cur = current; int change = 0; int lost = 0; if (0 == updated) { return; } Segment seg = new Segment(0); seg.conv = conv; seg.cmd = IKCP_CMD_ACK; seg.wnd = wnd_unused(); seg.una = rcv_nxt; // flush acknowledges int count = acklist.Count / 2; int offset = 0; for (int i = 0; i < count; i++) { if (offset + IKCP_OVERHEAD > mtu) { this.output.output(buffer, this, user); offset = 0; buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); } seg.sn = acklist[i * 2 + 0]; seg.ts = acklist[i * 2 + 1]; offset += seg.Encode(buffer); } acklist.Clear(); // probe window size (if remote window size equals zero) if (0 == rmt_wnd) { if (0 == probe_wait) { probe_wait = IKCP_PROBE_INIT; ts_probe = current + probe_wait; } else if (_itimediff(current, ts_probe) >= 0) { if (probe_wait < IKCP_PROBE_INIT) { probe_wait = IKCP_PROBE_INIT; } probe_wait += probe_wait / 2; if (probe_wait > IKCP_PROBE_LIMIT) { probe_wait = IKCP_PROBE_LIMIT; } ts_probe = current + probe_wait; probe |= IKCP_ASK_SEND; } } else { ts_probe = 0; probe_wait = 0; } // flush window probing commands if ((probe & IKCP_ASK_SEND) != 0) { seg.cmd = IKCP_CMD_WASK; if (offset + IKCP_OVERHEAD > mtu) { this.output.output(buffer, this, user); offset = 0; buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); } offset += seg.Encode(buffer); } probe = 0; // calculate window size int cwnd_ = Math.Min(snd_wnd, rmt_wnd); if (0 == nocwnd) { cwnd_ = Math.Min(cwnd, cwnd_); } count = 0; for (int i = 0; i < snd_queue.Count; i++) { if (_itimediff(snd_nxt, snd_una + cwnd_) >= 0) { break; } Segment newseg = snd_queue[i]; newseg.conv = conv; newseg.cmd = IKCP_CMD_PUSH; newseg.wnd = seg.wnd; newseg.ts = cur; newseg.sn = snd_nxt; newseg.una = rcv_nxt; newseg.resendts = cur; newseg.rto = rx_rto; newseg.fastack = 0; newseg.xmit = 0; snd_buf.Add(newseg); snd_nxt++; count++; } if (0 < count) { for (int i = 0; i < count; i++) { snd_queue.RemoveAt(0); } } // calculate resent int resent = fastresend; if (fastresend <= 0) { resent = -1; } int rtomin = rx_rto >> 3; if (nodelay != 0) { rtomin = 0; } // flush data segments for (int i = 0; i < snd_buf.Count; i++) { Segment segment = snd_buf[i]; bool needsend = false; //int debug = _itimediff(cur, segment.resendts); if (0 == segment.xmit) { needsend = true; segment.xmit++; segment.rto = rx_rto; segment.resendts = cur + segment.rto + rtomin; } else if (_itimediff(cur, segment.resendts) >= 0) { needsend = true; segment.xmit++; xmit++; if (0 == nodelay) { segment.rto += rx_rto; } else { segment.rto += rx_rto / 2; } segment.resendts = cur + segment.rto; lost = 1; } else if (segment.fastack >= resent) { needsend = true; segment.xmit++; segment.fastack = 0; segment.resendts = cur + segment.rto; change++; } if (needsend) { segment.ts = cur; segment.wnd = seg.wnd; segment.una = rcv_nxt; int need = IKCP_OVERHEAD + segment.data.ReadableBytes(); if (offset + need >= mtu) { this.output.output(buffer, this, user); buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); offset = 0; } offset += segment.Encode(buffer); if (segment.data.ReadableBytes() > 0) { offset += segment.data.ReadableBytes(); buffer.WriteBytes(segment.data); } if (segment.xmit >= dead_link) { state = 0; } } } // flash remain segments if (offset > 0) { this.output.output(buffer, this, user); buffer = new ByteBuf((mtu + IKCP_OVERHEAD) * 3); } // update ssthresh if (change != 0) { int inflight = snd_nxt - snd_una; ssthresh = inflight / 2; if (ssthresh < IKCP_THRESH_MIN) { ssthresh = IKCP_THRESH_MIN; } cwnd = ssthresh + resent; incr = cwnd * mss; } if (lost != 0) { ssthresh = cwnd / 2; if (ssthresh < IKCP_THRESH_MIN) { ssthresh = IKCP_THRESH_MIN; } cwnd = 1; incr = mss; } if (cwnd < 1) { cwnd = 1; incr = mss; } }
/** * 写入一些字节 **/ public Frame PutBytes(ByteBuf src) { if (!end) payload.WriteBytes(src); return this; }
public Frame(int len) { this.payload = new ByteBuf(len); payload.WriteShort(0); }
/** * * when you received a low level packet (eg. UDP packet), call it * * @param data * @return */ public int Input(ByteBuf data) { int una_temp = snd_una; int flag = 0, maxack = 0; if (data == null || data.ReadableBytes() < IKCP_OVERHEAD) { return(-1); } while (true) { bool readed = false; int ts; int sn; int len; int una; int conv_; int wnd; byte cmd; byte frg; if (data.ReadableBytes() < IKCP_OVERHEAD) { break; } conv_ = data.ReadIntLE(); if (this.conv != conv_) { return(-1); } cmd = data.ReadByte(); frg = data.ReadByte(); wnd = data.ReadShortLE(); ts = data.ReadIntLE(); sn = data.ReadIntLE(); una = data.ReadIntLE(); len = data.ReadIntLE(); if (data.ReadableBytes() < len) { return(-2); } switch ((int)cmd) { case IKCP_CMD_PUSH: case IKCP_CMD_ACK: case IKCP_CMD_WASK: case IKCP_CMD_WINS: break; default: return(-3); } rmt_wnd = wnd & 0x0000ffff; Parse_una(una); Shrink_buf(); switch (cmd) { case IKCP_CMD_ACK: if (_itimediff(current, ts) >= 0) { Update_ack(_itimediff(current, ts)); } Parse_ack(sn); Shrink_buf(); if (flag == 0) { flag = 1; maxack = sn; } else if (_itimediff(sn, maxack) > 0) { maxack = sn; } break; case IKCP_CMD_PUSH: if (_itimediff(sn, rcv_nxt + rcv_wnd) < 0) { Ack_push(sn, ts); if (_itimediff(sn, rcv_nxt) >= 0) { Segment seg = new Segment(len); seg.conv = conv_; seg.cmd = cmd; seg.frg = frg & 0x000000ff; seg.wnd = wnd; seg.ts = ts; seg.sn = sn; seg.una = una; if (len > 0) { seg.data.WriteBytes(data, len); readed = true; } Parse_data(seg); } } break; case IKCP_CMD_WASK: // ready to send back IKCP_CMD_WINS in Ikcp_flush // tell remote my window size probe |= IKCP_ASK_TELL; break; case IKCP_CMD_WINS: // do nothing break; default: return(-3); } if (!readed) { data.SkipBytes(len); } } if (flag != 0) { Parse_fastack(maxack); } if (_itimediff(snd_una, una_temp) > 0) { if (this.cwnd < this.rmt_wnd) { if (this.cwnd < this.ssthresh) { this.cwnd++; this.incr += mss; } else { if (this.incr < mss) { this.incr = mss; } this.incr += (mss * mss) / this.incr + (mss / 16); if ((this.cwnd + 1) * mss <= this.incr) { this.cwnd++; } } if (this.cwnd > this.rmt_wnd) { this.cwnd = this.rmt_wnd; this.incr = this.rmt_wnd * mss; } } } return(0); }
/** * user/upper level recv: returns size, returns below zero for EAGAIN * * @param buffer * @return */ public int Receive(ByteBuf buffer) { if (rcv_queue.Count <= 0) { return(-1); } int peekSize = PeekSize(); if (0 > peekSize) { return(-2); } if (peekSize > buffer.WritableBytes()) { return(-3); } bool fast_recover = false; if (rcv_queue.Count >= rcv_wnd) { fast_recover = true; } // merge fragment. int count = 0; int n = 0; for (int i = 0; i < rcv_queue.Count; i++) { Segment seg = rcv_queue[i]; n += seg.data.ReadableBytes(); buffer.WriteBytes(seg.data); count++; if (0 == seg.frg) { break; } } if (0 < count) { for (int i = 0; i < count; i++) { rcv_queue.RemoveAt(0); } } // move available data from rcv_buf -> rcv_queue count = 0; for (int i = 0; i < rcv_buf.Count; i++) { Segment seg = rcv_buf[i]; if (seg.sn == rcv_nxt && rcv_queue.Count < rcv_wnd) { rcv_queue.Add(seg); rcv_nxt++; count++; } else { break; } } if (0 < count) { for (int i = 0; i < count; i++) { rcv_buf.RemoveAt(0); } } // fast recover if (rcv_queue.Count < rcv_wnd && fast_recover) { // ready to send back IKCP_CMD_WINS in ikcp_flush // tell remote my window size probe |= IKCP_ASK_TELL; } return(n); }
private long bytesSended; //已经发送出去的字节数量 /** * 构造(但不完善,需要设置监听器和协议解析器) */ public USocket() { buf = new ByteBuf(4096); //queue = new BlockingQueue<ByteBuf>(5000); }
/** * Create a new {@code CodedOutputStream} wrapping the given * {@code OutputStream} with a given buffer size. * * @param output * @param bufferSize * @return */ public static CodedOutputStream newInstance( ByteBuf output, int bufferSize) { return new CodedOutputStream(output, new byte[bufferSize]); }
/** * 处理收到的消息 */ protected abstract void HandleReceive(ByteBuf bb);
/** * 连接成功 */ private void connected(IAsyncResult asyncConnect) { if (this.clientSocket.Connected) { this.clientSocket.EndConnect(asyncConnect); this.status = STATUS_CONNECTED; this.listner.OnOpen (this); ByteBuf buf=new ByteBuf(4096); Thread thread = new Thread(new ThreadStart(receive)); thread.IsBackground = true; thread.Start(); } }
/** * * when you received a low level packet (eg. UDP packet), call it * * @param data * @return */ public int Input(ByteBuf data) { int s_una = snd_una; if (data == null || data.ReadableBytes() < IKCP_OVERHEAD) { return(-1); } int offset = 0; while (true) { int ts; int sn; int length; int una; int conv_; int wnd; byte cmd; byte frg; if (data.ReadableBytes() < IKCP_OVERHEAD) { break; } conv_ = data.ReadInt(); offset += 4; if (conv != conv_) { return(-1); } cmd = data.ReadByte(); offset += 1; frg = data.ReadByte(); offset += 1; wnd = data.ReadShort(); offset += 2; ts = data.ReadInt(); offset += 4; sn = data.ReadInt(); offset += 4; una = data.ReadInt(); offset += 4; length = data.ReadInt(); offset += 4; if (data.ReadableBytes() < length) { return(-2); } switch ((int)cmd) { case IKCP_CMD_PUSH: case IKCP_CMD_ACK: case IKCP_CMD_WASK: case IKCP_CMD_WINS: break; default: return(-3); } rmt_wnd = wnd & 0x0000ffff; parse_una(una); shrink_buf(); switch (cmd) { case IKCP_CMD_ACK: if (_itimediff(current, ts) >= 0) { update_ack(_itimediff(current, ts)); } parse_ack(sn); shrink_buf(); break; case IKCP_CMD_PUSH: if (_itimediff(sn, rcv_nxt + rcv_wnd) < 0) { ack_push(sn, ts); if (_itimediff(sn, rcv_nxt) >= 0) { Segment seg = new Segment(length); seg.conv = conv_; seg.cmd = cmd; seg.frg = frg & 0x000000ff; seg.wnd = wnd; seg.ts = ts; seg.sn = sn; seg.una = una; if (length > 0) { seg.data.WriteBytes(data, length); } parse_data(seg); } } break; case IKCP_CMD_WASK: // ready to send back IKCP_CMD_WINS in Ikcp_flush // tell remote my window size probe |= IKCP_ASK_TELL; break; // do nothing case IKCP_CMD_WINS: break; default: return(-3); } offset += length; } if (_itimediff(snd_una, s_una) > 0) { if (cwnd < rmt_wnd) { int mss_ = mss; if (cwnd < ssthresh) { cwnd++; incr += mss_; } else { if (incr < mss_) { incr = mss_; } incr += (mss_ * mss_) / incr + (mss_ / 16); if ((cwnd + 1) * mss_ <= incr) { cwnd++; } } if (cwnd > rmt_wnd) { cwnd = rmt_wnd; incr = rmt_wnd * mss_; } } } return(0); }
/** * 写入一部分字节 **/ public ByteBuf WriteBytes(ByteBuf src) { int sum = src.writerIndex - src.readerIndex; Capacity(writerIndex + sum); if (sum > 0) { Array.Copy (src.data, src.readerIndex, data, writerIndex, sum); writerIndex += sum; src.readerIndex += sum; } return this; }