Giter Site home page Giter Site logo

kcp's People

Contributors

gsw945 avatar kumokyaku avatar liguanyu avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

kcp's Issues

频繁开辟内存的性能问题

如果服务器端连接1000+客户端,内存开辟耗时问题
比如这样的:
var seg = KcpSegment.AllocHGlobal(size);
buffer.Slice(offset, size).CopyTo(seg.data);
offset += size;
seg.frg = (byte)(count - i - 1);
snd_queue.Enqueue(seg);
建议实现 ArraySegment对内存块重复利用

TryRecv() = Object reference not set to an instance of an object

When sending packets (repeadetly 100+) 3-5 times, then null reference exception occurs.

Important. This ONLY happens when using

new PoolSegManager.Kcp()

and loop without delay/sleep.

With sleep/delay 1 then there is no issue.

Example error code:

var kcp = new PoolSegManager.Kcp(12, this);
kcp.NoDelay(1, 10, 2, 1);
kcp.WndSize(64, 64);
kcp.SetMtu(512);

Task.Run(() =>
            {
                while (true)
                {
                    kcp.Update(DateTime.UtcNow);

                    try
                    {
                        int len;
                        do
                        {
                            var (buffer, avalidSzie) = kcp.TryRecv();
                            len = avalidSzie;
                            if (buffer != null)
                            {
                                buffer.Dispose();
                            }
                        } while (len > 0);
                    }
                    catch(Exception e)
                    {
                        Console.WriteLine(e);
                    }
                }
            });

Untitled

如何保证客户端和服务端conv值一致

大佬您好..萌新有一些问题想请教一下

我的理解是客户端和服务端的conv值需要一致才能建立起kcp的”连接“,然后服务端管理N个kcp对象维护这些“连接”
但是客户端在连接到服务器之前,不知道conv应该是多少,也就不能初始化kcp,而为了让服务器的conv不会重复,只能是在服务器分配conv..

目前想到的是先进行TCP连接交换conv一致后再初始化kcp,不知道是否是正确的用法,如果不是请问通常会如何做

谢谢您抽出宝贵的时间解答

流模式

有限的支持流模式。
虽然无法追加数据到最后一个包,但可以frg保持为0.

请教作者一些问题

第一次使用,有几点问题想请教下:
1、长连接游戏开发,前端如果没有特殊需求,是否直接用SimpleKcpClient就可以
2、服务端用SimpleKcpClient如何区分不同客户端、Session
3、是否需要自己处理粘包
4、超大数据包,是否需要自行分割成几个小数据包发送

谢谢!

线程安全问题

1457行 foreach (var seg in snd_buf)

存在线程安全问题,在另外线程中执行Dispose,snd_buf为产生空引用异常。

可能出现了数据虚报长度?

首先还是要感谢大佬开发的线程安全版的C# KCP,十分实用!

image

之前在服务器的日志中 (服务器并非C#代码) 找到一些 KCP 数据包报错,于是写了一些代码,截下Output回调发出的包检查数据是否存在问题。

期间一共发了约 4000-5000 个基础 UDP 包(单个KCP实例),服务器在内网虚拟机,程序检查到了 51 次数据损坏。

具体情况是:data 部分的数据长度与 len 不符。可能会长,也可能会短,但是包实际的有效大小与 len 相同。

更具体地,我的所有包在加密前都带有包特征(开头0x4567和结尾0x89AB),如果data的实际长度比len小,可以找到包头但找不到尾部,input触发-2;如果data的实际长度比len大,则有包头并可以在len - 2处找到包尾,但后面的内容(指在下一个分片前的内容)既不是空包也不是外部Send的内容,input会触发-1.

贴几个典型一点的日志,下面是data比len小的:

13:38:38 <Warn:KcpPacketAudit> Detected invalid kcp packet sent at 2023/5/14 13:38:38, bytes_sent=72
13:38:38 <Dbug:KcpPacketAudit> 
----------KcpPacketAudit report----------
Detected following exceptions:
  Segment 0's content length is shorter that reported: 48 bytes, Content (44 bytes): 7BB688DC18DBBB7DDF8823686397EE96A0EC4CC9B26819FA33E24D0E998CCCC134594602637D80301B8417DC

Raw packet (conv=1011, token=4229662954): F3030000EA881BFC51000001A89EC418A70C000014120000300000007BB688DC18DBBB7DDF8823686397EE96A0EC4CC9B26819FA33E24D0E998CCCC134594602637D80301B8417DC

Segment 0: Range 0 +72bytes
  cmd=81, frg=0, wnd=256, ts=415538856, sn=3239, una=4628
  Content (reported: 48bytes, actual: 44bytes): 
    7BB688DC18DBBB7DDF8823686397EE96A0EC4CC9B26819FA33E24D0E998CCCC134594602637D80301B8417DC

-----------------------------------------

下面是data比len大的:

13:38:37 <Warn:KcpPacketAudit> Detected invalid kcp packet sent at 2023/5/14 13:38:37, bytes_sent=76
13:38:37 <Dbug:KcpPacketAudit> 
----------KcpPacketAudit report----------
Detected following exceptions:
  Segment 0's content length is longer that reported, Content: 
Range 28 +36bytes (reported): 7BB68AF318DBBB7DDF9C233B6397EE96A4E04CC9B26829F943CD4D0EB1961514F166F196
Range 64 +12bytes (exceeded): 63B4C7411C84987211EA41A6

Raw packet (conv=1011, token=4229662954): F3030000EA881BFC5100FF008F98C418760C0000F3110000240000007BB68AF318DBBB7DDF9C233B6397EE96A4E04CC9B26829F943CD4D0EB1961514F166F19663B4C7411C84987211EA41A6

Segment 0: Range 0 +76bytes
  cmd=81, frg=0, wnd=255, ts=415537295, sn=3190, una=4595
  Content (reported: 36bytes, actual: 48bytes): 
    7BB68AF318DBBB7DDF9C233B6397EE96A4E04CC9B26829F943CD4D0EB1961514F166F19663B4C7411C84987211EA41A6

-----------------------------------------

即使是程序逻辑上的问题,似乎也不应出现实际data的长度与len不符的情况。

服务器和客户端的代码都不太方便公开(其实是没有),所以排错之类我自己会来做。大佬有什么debug的建议吗?比如:

  • Memory 传入 Kcp.Send 后发生更改(包括被释放)会不会造成影响?
  • 您的KCP实现在哪些地方有分配内存的实现?
  • 我可能应该在什么地方 Assert?

上文日志使用的 KcpPacketAudit.cs

(注:程序使用的是一种变种的KCP,在conv后面插入了4字节当作token,每次连接时生成的一个随机数,以后input进来的包token不符合则丢弃返回-1)

请教rcv_queue的数据结构问题

作者您好,我有一处不解:rcv_queue为何使用的是List而非ConcurrentQueue,我在学习时尝试替换为后者,似乎可行?

已发送的数据包在超过dead_link仍在尝试继续发送

作者您好,很幸运能使用到开发如此便捷的C# KCP库。在使用中遇到一个疑问:
在使用KCP像未启动KCP服务的主机发送数据包时,客户端会启动自动重传,但是重传次数超过dead_link后,虽然state为-1,但是重传仍在继续。
想知道有什么办法可以使其停止对那个数据包的重传吗。
谢谢作者!

关于UnsafeSegManager疑似错误分配内存的问题

由于我上次来提issue的时候似乎没有做好工作,因此这里先叠个甲:
我自己的上层协议栈与Kcp内部(Recv,循环调用Update)都保证了正确的单线程调用,保证这部分没有出现问题。
SingleThreadAssert.cs.txt


我正在做一点协议栈的测试工作,但是观察到了在测试发包压力巨大(10ms一次发包)的时候出现了严重的丢包。更确切地说,是包可能出现中间内容异位,或是包被掐头去尾(比较形象的描述)。

下面是两张现象截图(图中监视的是rcv_queue):

屏幕截图 2023-06-09 223519

屏幕截图 2023-06-09 232508

经过亿点点调试工作,最终确认了大概是使用了UnsafeSegManager的问题。

image

观察这幅图高亮的部分。Send 所使用的 KcpSegment 与 Input 中的一个 Segment 竟然共享一个 ptr,我不知道这是否是预期之内的情况。
这个包在 Flush 出口的时候被 Debug.Assert 拦下了,还没有 Flush 出去,应该不存在可能内存释放掉重用了的情况。再放一张 NEED_SEND 的日志证明一下:

image

切换到 SimpleSegManager 后没有出现过类似问题。PoolSegManager 没有测试过,主要因为它换了一个 Segment 类型,暂时不想做更多调试了。

发生了数据损坏的现象

'
for (int i = 0; i < 30; i++)
{
clientSt.kcp.Send(Encoding.UTF8.GetBytes($"第{i}次数据_{DateTime.Now}"));
}
'
在第9次,第17次时,大概率出现数据损坏,“据”位置乱码

以下是数据接收代码:
'
client.kcp.Update(DateTime.UtcNow);
int readLength = client.kcp.PeekSize();
while (readLength > 0)
{
var bytes = new byte[readLength];
int length = client.kcp.Recv(bytes);
if (length > 0)
{
//todo:已经接收到完整包
Console.WriteLine(Encoding.UTF8.GetString(bytes.Take(length).ToArray()));
}
readLength = client.kcp.PeekSize();
}
'

2个客户端请求一个服务器时有一个客户端不会收到消息

用的TestClient启动了2个客户端,但是有一个客户端收不到消息。下面时客户端的修改代码

using System;
using System.Buffers;
using System.Diagnostics;
using System.Net;
using System.Net.Sockets;
using System.Net.Sockets.Kcp;
using System.Net.Sockets.Kcp.Simple;
using System.Threading.Tasks;

namespace TestClient
{
class Program
{
public class TestClient
{
public string guid;

        public void Init(string guid,int prot,uint uit)
        {
            this.guid = guid;
            SimpleKcpClient kcpClient = new SimpleKcpClient(prot, uit,end);
            kcpClient.kcp.TraceListener = new ConsoleTraceListener();
            Task.Run(async () =>
            {
                while (true)
                {
                    kcpClient.kcp.Update(DateTimeOffset.UtcNow);
                    await Task.Delay(10);
                }
            });
            Task.Run(async () =>
            {
                while (true)
                {
                    // var k = Console.ReadKey();
                    // if (k.Key == ConsoleKey.A)
                    {
                        Send(kcpClient, "发送一条消息" + guid);
                    }
                    await Task.Delay(0);
                }
            });
        }

        static IPEndPoint end = new System.Net.IPEndPoint(System.Net.IPAddress.Loopback, 40001);

         async void Send(SimpleKcpClient client, string v)
        {
            var buffer = System.Text.Encoding.UTF8.GetBytes(v);
            client.SendAsync(buffer, buffer.Length);
            var resp = await client.ReceiveAsync();
            var respstr = System.Text.Encoding.UTF8.GetString(resp);
            Console.WriteLine($"{guid}  收到服务器回复:    {respstr}");
        }
    }

    static void Main(string[] args)
    {
        Console.WriteLine("Press F1 send word.......");

        TestClient testClient = new TestClient();
        testClient.Init("客户端1号",50001,2001);
        TestClient ttt2 = new TestClient();
        ttt2.Init("客户端2号",50002,2001);
        Console.ReadLine();
    }
}

}

支持unity使用吗?

unity目前只支持.net stand2.0
kcp代码在.net standard2.0下编译不过
因为使用了.net standard2.1里的Buffers,Memory<>,Span<>等

请问要在unity里使用kcp要怎么做?
谢谢

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.