1 Commits
v2 ... 2.0.0

4 changed files with 73 additions and 39 deletions

69
.gitignore vendored
View File

@@ -1,14 +1,69 @@
*.o
*
!*/
!*.*
*.obj
*.o
*.lib
*.ipch
*.pch
*.sdf
*.exe
*.a
*.p
*.dll
*.so
*.dylib
*.ncb
*.sdf
.tasks
.root
__pycache__
/build/*
/example/build/*
/gateway/build/*
/.vscode/*
/.idea/*
/.DS_Store
/.env
/build/*
/.vs/*
/.cache/*
/testing/*.xlsx
/testing/*.txt
/update.cmd
.vs
/visualstudio/Debug/*
/visualstudio/Release/*
/visualstudio/x64/*
/visualstudio/bbnet/*
/visualstudio/.vs/*
/visualstudio/bbnet.vcxproj.user
/x64/*
/Debug/*
/Release/*
/bbnet/*
*.vcxproj.user
/update.cmd
*.pcap
*.win32
*.linux
*.linux2
*.log
*.pyc
*.pyo
*.pyd
__pycache__/*
/session*.md
/skills/*
/.qoder/*
/.opencode/*
/.claude/*
/.iflow/*
nul

View File

@@ -22,6 +22,8 @@ KCP是一个快速可靠协议能以比 TCP 浪费 10%-20% 的带宽的代价
整个协议只有 ikcp.h, ikcp.c两个源文件可以方便的集成到用户自己的协议栈中。也许你实现了一个P2P或者某个基于 UDP的协议而缺乏一套完善的ARQ可靠协议实现那么简单的拷贝这两个文件到现有项目中稍微编写两行代码即可使用。
**注意KCP 目前更新到 V2增加了可插拔的流控算法机制可以不改协议的情况下替换流控算法老的 v1 足够稳定,我放到了 v1 这个 branch 里。**
# 技术特性

35
ikcp.c
View File

@@ -272,7 +272,6 @@ ikcpcb* ikcp_create(IUINT32 conv, void *user)
kcp->acklist = NULL;
kcp->ackblock = 0;
kcp->ackcount = 0;
kcp->ackedlen = 0;
kcp->rx_srtt = 0;
kcp->rx_rttval = 0;
kcp->rx_rto = IKCP_RTO_DEF;
@@ -596,7 +595,6 @@ static void ikcp_parse_ack(ikcpcb *kcp, IUINT32 sn)
IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
next = p->next;
if (sn == seg->sn) {
kcp->ackedlen += seg->len;
if (kcp->ccops && kcp->ccops->on_pkt_acked) {
pkt_rtt = -1;
if (_itimediff(kcp->current, seg->ts) >= 0) {
@@ -623,7 +621,6 @@ static void ikcp_parse_una(ikcpcb *kcp, IUINT32 una)
IKCPSEG *seg = iqueue_entry(p, IKCPSEG, node);
next = p->next;
if (_itimediff(una, seg->sn) > 0) {
kcp->ackedlen += seg->len;
if (kcp->ccops && kcp->ccops->on_pkt_acked) {
kcp->ccops->on_pkt_acked(kcp, seg->sn, seg->ts,
seg->len, -1, seg->xmit);
@@ -785,8 +782,6 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size)
IUINT32 maxack = 0, latest_ts = 0;
int flag = 0;
kcp->ackedlen = 0;
if (ikcp_canlog(kcp, IKCP_LOG_INPUT)) {
ikcp_log(kcp, IKCP_LOG_INPUT, "[RI] %d bytes", (int)size);
}
@@ -911,8 +906,7 @@ int ikcp_input(ikcpcb *kcp, const char *data, long size)
acked_segs = kcp->snd_una - prev_una;
prior_in_flight = prev_nsnd_buf;
if (kcp->ccops && kcp->ccops->on_ack) {
kcp->ccops->on_ack(kcp, acked_segs, kcp->ackedlen,
prior_in_flight);
kcp->ccops->on_ack(kcp, acked_segs, prior_in_flight);
}
else {
if (kcp->cwnd < kcp->rmt_wnd) {
@@ -981,7 +975,6 @@ void ikcp_flush(ikcpcb *kcp)
IUINT32 rtomin;
IUINT32 prior_cwnd;
IUINT32 eff_cwnd, cur_inflight;
IINT32 pacing_budget = -1;
struct IQUEUEHEAD *p;
int change = 0;
int lost = 0;
@@ -994,10 +987,6 @@ void ikcp_flush(ikcpcb *kcp)
kcp->ccops->on_tick(kcp);
}
if (kcp->ccops && kcp->ccops->pacing_rate) {
pacing_budget = (IINT32)kcp->ccops->pacing_rate(kcp);
}
prior_cwnd = kcp->cwnd;
seg.conv = kcp->conv;
@@ -1095,6 +1084,10 @@ void ikcp_flush(ikcpcb *kcp)
newseg->rto = kcp->rx_rto;
newseg->fastack = 0;
newseg->xmit = 0;
if (kcp->ccops && kcp->ccops->on_pkt_sent) {
kcp->ccops->on_pkt_sent(kcp, newseg->sn, current, newseg->len, kcp->nsnd_buf - 1);
}
}
// check on_app_limited
@@ -1154,15 +1147,6 @@ void ikcp_flush(ikcpcb *kcp)
segment->wnd = seg.wnd;
segment->una = kcp->rcv_nxt;
if (pacing_budget >= 0 && pacing_budget < (IINT32)segment->len) {
break;
}
if (kcp->ccops && kcp->ccops->on_pkt_sent) {
kcp->ccops->on_pkt_sent(kcp, segment->sn, current,
segment->len, kcp->nsnd_buf, segment->xmit);
}
size = (int)(ptr - buffer);
need = IKCP_OVERHEAD + segment->len;
@@ -1178,10 +1162,6 @@ void ikcp_flush(ikcpcb *kcp)
ptr += segment->len;
}
if (pacing_budget >= 0) {
pacing_budget -= (IINT32)segment->len;
}
if (segment->xmit >= kcp->dead_link) {
kcp->state = (IUINT32)-1;
}
@@ -1197,8 +1177,7 @@ void ikcp_flush(ikcpcb *kcp)
// update ssthresh
if (change) {
if (kcp->ccops && kcp->ccops->on_fast_retransmit) {
kcp->ccops->on_fast_retransmit(kcp, (IUINT32)change,
kcp->nsnd_buf, prior_cwnd);
kcp->ccops->on_fast_retransmit(kcp, (IUINT32)change, kcp->nsnd_buf, prior_cwnd);
}
else {
IUINT32 inflight = kcp->snd_nxt - kcp->snd_una;
@@ -1215,7 +1194,7 @@ void ikcp_flush(ikcpcb *kcp)
kcp->ccops->on_timeout(kcp, prior_cwnd);
}
else {
kcp->ssthresh = prior_cwnd / 2;
kcp->ssthresh = cwnd / 2;
if (kcp->ssthresh < IKCP_THRESH_MIN)
kcp->ssthresh = IKCP_THRESH_MIN;
kcp->cwnd = 1;

6
ikcp.h
View File

@@ -298,8 +298,7 @@ struct IKCPOPS
const char *name;
int (*init)(ikcpcb *kcp);
void (*release)(ikcpcb *kcp);
void (*on_ack)(ikcpcb *kcp, IUINT32 acked_segs, IUINT32 acked_bytes,
IUINT32 prior_in_flight);
void (*on_ack)(ikcpcb *kcp, IUINT32 acked_segs, IUINT32 prior_in_flight);
void (*on_fast_retransmit)(ikcpcb *kcp, IUINT32 fast_retrans,
IUINT32 inflight, IUINT32 prior_cwnd);
void (*on_timeout)(ikcpcb *kcp, IUINT32 prior_cwnd);
@@ -307,7 +306,7 @@ struct IKCPOPS
void (*on_app_limited)(ikcpcb *kcp, IUINT32 inflight);
void (*on_rtt)(ikcpcb *kcp, IINT32 rtt);
void (*on_pkt_sent)(ikcpcb *kcp, IUINT32 sn, IUINT32 ts,
IUINT32 len, IUINT32 inflight, IUINT32 xmit);
IUINT32 len, IUINT32 inflight);
void (*on_pkt_acked)(ikcpcb *kcp, IUINT32 sn, IUINT32 ts,
IUINT32 len, IINT32 rtt, IUINT32 xmit);
IUINT32 (*get_info)(ikcpcb *kcp, void *buf, IUINT32 bufsize);
@@ -338,7 +337,6 @@ struct IKCPCB
IUINT32 *acklist;
IUINT32 ackcount;
IUINT32 ackblock;
IUINT32 ackedlen;
void *user;
char *buffer;
int fastresend;