2023
08-02

kcp

kcp源码

kcp - 第1张  | bonoStallone 明天的烟火
kcp - 第2张  | bonoStallone 明天的烟火

里面有IKCP_WND_RCV 常量值

kcp
默认为128 那么可知 这个是包的总数量

count = (len + kcp->mss – 1) / kcp->mss;

kcp->mss = kcp->mtu – IKCP_OVERHEAD;

也就是1400-24=1376

带入式子
128=(x+1376-1)/1376

则x=174753 则当x=174753时候 数据刚好过不去 那么就是174752为最大值

我定义的包头为 4(crc)+8(sNo)+4(totalPage)+4(currentPage)+4(dataSize)=24

则纯数据为174728

发送分包数据结构为 crc+sNo+totalPage+currentPage+dataSize+data

总包数据结构为 messageId+oriDataLength+compressDataLength+data

发送流程

SendMessage(int messageId,byte[] buffer)
{
compressData=Compress(buffer);
stream s =new stream;
s.reset;
s.writeUint32(messageId);
s.writeUint32(buffer.length);
s.writeUint32(compressData.Length);

Splitpackage(messageId,s.tobyte[]);

}

Splitpackage(int messageId,byte[] bytes)
{
stream s=new stream;
int MaxPageSize=x; //这个就是上文的X
int remain=bytes.length%x;

int totalPage=0;
int currentPage=0;
if(remain==0)
{
    totalPage=bytes.length/MaxPageSize;
}
else
{
    totalPage=bytes.length/MaxPageSize+1;
}

int begain=0;
int copylen=MaxPageSize;

for(int i=0;i<totalPage;i++)
{
    currentPage=i+1;
    begain=i*MaxPageSize;
    if(i==totalPage-1)
    {
        copylen=bytes.length-begain;
    }
    else
    {
        copylen=MaxPageSize;
    }

    arraySegment<byte> data=new arraySegment<byte>(bytes,begain,copylen).toArray();

    s.reset;
    kcpNo+=1;

    s.writeUint64(kcpNo);
    s.writeUint32(totalPage);
    s.writeUint32(currentPage);
    s.writeUint32(copylen);
    s.write(data.array);

    uint crc=calcCrc(s.tobyte);

    s.writeUint32(crc);
    s.writeUint64(kcpNo);
    s.writeUint32(totalPage);
    s.writeUint32(currentPage);
    s.writeUint32(copylen);
    s.write(data.array);

    send(s.toArray);
}

}

接收流程

void PrePack(byte[] pack)
{
stream s=new stream();
s.write(pack);
uint crc=readUnit32();
ulong kcpNo=readUnit64();
uint totalPage=readUnit32();
uint currentPage=readUnit32();
uint size=readUnit32();

arraySegment<byte> dataBuffer=new arraySegment<byte>(pack,s.position,dataSize);

int size=8+4+4+4+dataSize;

arraySegment<byte> crcBuffer=new arraySegment<byte>(pack,4,size);

if(!crcIsVaild(crcBuffer,crc))
{
    crc error;
}

if(totalPage==1)
{
    if(currentPage==1)
    {
        UnpackNew(dataBuffer.toArray);
    }
}
else if(totalPage>1)
{
    if(currentPage==1)
    {
        onepackSteam.position=0
    }

    onepackSteam.write(dataBuffer.toArray);

    if(currentPage==totalPage)
    {
        UnpackNew(onepackSteam.toArray);
    }
}

}

void UnpackNew(byte[] buffer)
{
unpackstream.position=0;
unpackstream.write(buffer,0,buffer.length);
unpackstream.position=0;

 uint messid=readUnit32(unpackstream);
 uint messageLen=readUnit32(unpackstream);
 uint messcomLenth=readUnit32(unpackstream);


 arraySegment<byte> dataBuffer=new arraySegment<byte>(buffer,unpackstream.position,messcomLenth);

 if(messageLen!=messcomLenth)
 {
     byte[] uncompressData=Decompress(dataBuffer.toArray,messageLen);

     dataBuffer=uncompressData;
 }

 OnRecive(messageId,dataBuffer.toArray)

}

最后编辑:
作者:bono
这个作者貌似有点懒,什么都没有留下。