KCP源码解析系列(二)KCP协议结构体

一、KCP协议包

1.1 kcp协议包

kcp中只有一种数据包,不管是数据还是控制信息,都用这个数据包来表示

0               4   5   6       8 (BYTE)
+---------------+---+---+-------+
|     conv      |cmd|frg|  wnd  |
+---------------+---+---+-------+   8
|     ts        |     sn        |
+---------------+---------------+  16
|     una       |     len       |
+---------------+---------------+  24
|                               |
|        DATA (optional)        |
|                               |
+-------------------------------+

  1. conv (4 bytes): 会话号,用于区分不同的会话。由于kcp不处理握手,可以通过两端

  2. cmd (1 byte): 命令类型,可能的命令类型包括:

    • IKCP_CMD_PUSH(数据包)

    • IKCP_CMD_ACK(确认包)

    • IKCP_CMD_WASK(窗口探测包,请求对方告知窗口大小)

    • IKCP_CMD_WINS(窗口大小通告包,告知对方窗口大小)

  3. frg (1 byte): 分片标识,表示数据是否被分片及其序号。对于不分片的数据包,该值为 0。

  4. wnd (2 bytes): 窗口大小,用于流量控制。

  5. ts (4 bytes): 时间戳,用于计算往返时间(RTT)以及重传超时(RTO)。

  6. sn (4 bytes): 序号,用于数据包排序和确认。

  7. una (4 bytes): 未确认的序号,用于流量控制。

  8. len (4 bytes): 数据部分的长度。

1.2 kcp源码IKCPSEG结构体

//=====================================================================
// SEGMENT
//=====================================================================
struct IKCPSEG
{
	struct IQUEUEHEAD node;//链表节点,结构体类型 IQUEUEHEAD,用于把该分段加入到发送或接收队列的链表中。
	IUINT32 conv;
	IUINT32 cmd;
	IUINT32 frg;
	IUINT32 wnd;
	IUINT32 ts;
	IUINT32 sn;
	IUINT32 una;
	IUINT32 len;
	IUINT32 resendts;//重传时间戳,32 位整数,表示该分段下一次进行重传的时间戳。
	IUINT32 rto;//重传超时时间,32 位整数,表示该分段的重传超时时间。根据 ACK 的 RTT 值调整。
	IUINT32 fastack;//快速重传计数,32 位整数,表示该分段被其他数据包跳过的次数,用于快速重传机制。
	IUINT32 xmit;//传输次数,32 位整数,表示该分段已被发送的次数。
	char data[1];
};

二、IKCPCB

IKCPCB 结构体是 KCP 协议中控制块的核心数据结构,包含了连接状态、传输参数、缓存和控制信息等。这是整个 KCP 协议运作的核心,用于管理连接的各个方面。下面是对每个字段的详细解释,

看不懂没关系,后边会在流程中解释。

struct IKCPCB {
    IUINT32 conv;              // 会话 ID,用于区分不同的连接
    IUINT32 mtu;               // 最大传输单元大小,指网络层能够传输的最大数据包大小
    IUINT32 mss;               // 最大分段大小,为 MTU 减去固定的 KCP 头部大小
    IUINT32 state;             // 连接状态

    IUINT32 snd_una;           // 未确认的发送序号
    IUINT32 snd_nxt;           // 下一个发送序号
    IUINT32 rcv_nxt;           // 下一个接收序号

    IUINT32 ts_recent;         // 最近的时间戳
    IUINT32 ts_lastack;        // 最后一个确认包的时间戳
    IUINT32 ssthresh;          // 慢启动门限

    IINT32 rx_rttval;          // RTT 波动值
    IINT32 rx_srtt;            // 平滑后的 RTT 值
    IINT32 rx_rto;             // 重传超时时间
    IINT32 rx_minrto;          // 最小重传超时时间
    
    IUINT32 ff_recovery_point; // 快速恢复点

    IUINT32 snd_wnd;           // 发送窗口大小
    IUINT32 rcv_wnd;           // 接收窗口大小
    IUINT32 rmt_wnd;           // 远端窗口大小
    IUINT32 cwnd;              // 拥塞窗口大小
    IUINT32 probe;             // 探测变量

    IUINT32 current;           // 当前时间
    IUINT32 interval;          // 内部工作刷新间隔
    IUINT32 ts_flush;          // 下次刷新时间戳
    IUINT32 xmit;              // 传输次数
    IUINT32 next_send;         // 下一个发送时间

    IUINT32 nrcv_buf;          // 接收缓冲区大小
    IUINT32 nsnd_buf;          // 发送缓冲区大小
    IUINT32 nrcv_que;          // 接收队列大小
    IUINT32 nsnd_que;          // 发送队列大小
    
    IUINT32 wait_snd_bytes;    // 等待发送字节数
    IUINT32 wait_rcv_bytes;    // 等待接收字节数

    IUINT32 nodelay;           // 是否启用无延迟模式
    IUINT32 updated;           // 是否已更新

    IUINT32 ts_probe;          // 窗口探测时间
    IUINT32 probe_wait;        // 窗口探测等待时间

    IUINT32 dead_link;         // 最大重传次数,超过此次数认为连接失效
    IUINT32 incr;              // 拥塞窗口增加量

    IUINT32 ts_wait_ack;       // 等待 ACK 的时间戳
    IUINT32 flag_wait_ack;     // 等待 ACK 的标志
    IUINT32 ts_echo;           // ECHO 的时间戳
    
    pthread_mutex_t send_lock; // 发送锁,用于多线程环境
    struct IQUEUEHEAD snd_queue;  // 发送队列
    pthread_mutex_t recv_lock; // 接收锁,用于多线程环境
    struct IQUEUEHEAD rcv_queue;  // 接收队列
    struct IQUEUEHEAD snd_buf;    // 发送缓冲区
    struct IQUEUEHEAD rcv_buf;    // 接收缓冲区

    IUINT32 *acklist;          // 存储待发送的 ACK 列表
    IUINT32 ackcount;          // ACK 的数量
    IUINT32 ts_sack;           // SACK 时间戳
    IUINT32 ackblock;          // ACK 列表的大小(块大小)

    void *user;                // 用户数据
    void *user_send_queue;     // 用户发送队列
    void *user_recv_queue;     // 用户接收队列
    char *buffer;              // 缓冲区
    int fastresend;            // 快速重传标志
    int nocwnd;                // 关闭拥塞控制标志
    int stream;                // 流模式标志
    int logmask;               // 日志掩码
    int delay_ack;             // 延迟 ACK 处理

    void *ca_priv;             // 拥塞避免私用数据
    int (*output)(const char *buf, int len, struct IKCPCB *kcp, void *user); // 数据输出回调
    void (*writelog)(const char *log, struct IKCPCB *kcp, void *user);      // 日志写入回调
    int (*process_pkt)(void *user, int length, const char *input, char *output); // 数据包处理回调
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值