GithubHelp home page GithubHelp logo

kcp2k's Introduction

kcp2k

C# KCP based on the original C kcp.

Works with netcore and Unity.

Developed for Mirror Networking.

Questions & support on Mirror Networking Discord.

Features

  • Kcp.cs based on kcp.c v1.7, line-by-line translation to C#
  • Heavy test coverage
  • Fixed WND_RCV bug from original kcp
  • Optional high level C# code for client/server connection handling
  • Optional high level Unreliable channel added

Pull requests for bug fixes & tests welcome.

Unity

kcp2k works perfectly with Unity, see the Mirror repository's KcpTransport.

Allocations

The client is allocation free. The server's SendTo/ReceiveFrom still allocate.

Previously, where-allocation for a 25x reduction in server allocations. However:

  • It only worked with Unity's old Mono version.
  • It didn't work in Unity's IL2CPP builds, which are still faster than Mono + NonAlloc
  • It didn't work in regular C# projects.
  • Overall, the extra complexity is not worth it. Use IL2CPP instead.
  • Microsoft is considering to remove the allocation.

Remarks

  • Congestion Control should be left disabled. It seems to be broken in KCP.

kcp2k's People

Contributors

ansonkindred avatar cxxpxr avatar imerr avatar miwarnec avatar mrgadget1024 avatar neonaleon avatar paulpach 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

kcp2k's Issues

Long delay after paused

I am developing a game using the KCP, but I can not solve one problem in any way. Perhaps no one has come across it, or I just don't understand something.
The client plays, then let's say he dies, I show the ad unit. (It is known that at the moment of displaying the unit pauses the main stream) so I pause.

void Pause()
{
  client.Pause();
  isPause = true;
 // and send to server notify
}

 public void LateUpdate()
    {
        if (!isPause)
            client.Tick();
    }

And I send a message to the server so that it increases the timeout (so that there is no disconnection due to the timeout).
An advertisement is displayed, for example, I wait 30 seconds. Then I send a message to the server, it arrives quite quickly (~100 ms).
But the message received by the client (from Server) comes with a long delay of 3 or more seconds (sometimes up to 30 even).
After the first message received, everyone else arrives on time.
But if I send an Unreliable message, then it arrives without delay.
My settings:

noDelay = true
interval = 10
fastResend = 2, 
congestionWindow = false
sendWindowSize =  4096
receiveWindowSize = 4096

What could be wrong ? How to get out of the pause correctly so that long delays do not occur ?
On PC, I cannot reproduce this problem(If I pause in the editor, then a maximum delay of several seconds is obtained. Which theoretically shouldn't be either.), only on Android.

Feature request: Add access to client udp port (UDP hole punching)

Description

I need to know the client udp port which is randomly assigned to the socket, so I can use it to punch a UDP hole from the server to the client (f.e. Full-cone NAT).

SERVER:7777 =UDP-PUNCH=> CLIENT:<RANDOM>

Without access to the udp client port (socket port) I cannot punch these holes during the connection phase.

Feature request

Public method to access the assigned client udp port.

You did great work!

Thanks in advance and best regards,
Thomas

Client Connection Error Callback

Ill duplicate my post with additional details from Mirror's repo.

As i see there is no way to get client connection errors. 2 examples:

  1. Client connection error before client connect to server. Which means connection not even happend.
    Client Recv: failed to connect to ip=localhost port=7777 reason=System.Net.Sockets.SocketException (0x80004005)
    As a result game start showing loading screen, got this message at console and runs infinity loading screen because there is no way to catch it exept OnClientDisconnect which i dont need because it not make any sence. Because this method happend every time client disconnect, what i dont need. I need an error, to disable loading screen and show popup to client with error what happend to his game.

  2. Server and client different versions i have server running on previos version, and im trying to connect from new version and i have these warnings on console:
    id: 29556. This can happen if no handler was registered for this message.
    NetworkClient: failed to unpack and invoke message. Disconnecting.
    As a result, i start show loading screen, then i got these warnings, connection not happend and i have infinity loading screen. So i want to catch ANY client connection error and do my stuff, like show error popup or something OnClientError() doest work for it. Idk why, it just never called.

Mr.Gadget says:

These are unrelated issues and should be separate tickets.

Mirror has error events that the transport can raise, but the transport has to raise them. File a ticket with the transport's repo to raise NetworkClient.OnErrorEvent. Then you can override Network Manager's OnClientError(Exception exception).

You need to handle a version check with the server before it gets so far as to have broken handlers. Network Authenticator would be well suited to this.

As i understand form Mr.Gadet answer and my findings of kcp code, there is no call of OnErrorEvent on transport. And as a result i cant catch errors to run my code. I can use only OnClientDisconnect but it calls every time when client disconnect what i dont need. Both examples are just examples of client errors that i would like to catch and i can describe a bunch of other errors, but it doesnt metter what kind of errors, its not a point. In other words it would be good to catch ANY client connection error with Network Manager's OnClientError(Exception exception).

uncork max message size

see paul's kcp PR for possible fix.
-> we use the configured window sizes anyway
-> the limit on max message size is artificial
-> some people do like to send larger messages

imer Linux dropping connections after 100+ CCU because buffer sizes

from discord:

to further this: https://stackoverflow.com/a/2290848
looking at the /proc/net/udp6 one I can see many drops while doing the stress test with 100 clients: https://share.dl.je/2021/06/2021-06-13_19-00-55_UwDiLFug52.mp4
increasing the kernel bufffers (/proc/sys/net/core/wmem_default/max and /proc/sys/net/core/rmem_default/max) by 100x (as a quick validation) fixed the issue - no more drops!
this is also reflected by the c# socket .Receive-/.SendBufferSize
KCP Receive/Send Buffer is: 21299200/21299200 - the _max doesn't change those. need to adjust _default for that

500 ccu on linux kcp: https://share.dl.je/2021/06/2021-06-13_19-26-56_5ZDNb9zwiv.png

Will there be a non-Unity version?

Will this project look at creating a version of this package designed for outside of Unity?

I see that Telepathy does have projects for usage outside of Unity; and I wonder whether it's the explicit direction of kvp2k to be a Unity-only package.

cookie warnings

this one seems hard to reproduce.
gathering user reports in this thread.

https://discord.com/channels/343440455738064897/467961162558865408/1167190009401585814

Any ideas what would cause this to be spammed in console for headless dedicated server build? 

    Mirror v81.3.1
    Using dedicated server linux build with il2cpp
    Unity version 2022.2.10

This occasionally happens when I start the server, other times it works just fine (does not print this message).
I haven't spent much time looking into it, but wondering if anyone has seen this?

Thu Oct 26 19:32:45 UTC 2023: Mirror.NetworkLoop:NetworkEarlyUpdate()
Thu Oct 26 19:32:45 UTC 2023:
Thu Oct 26 19:32:45 UTC 2023: KcpPeer: dropped message with invalid cookie: 0 expected: 1052116154.

this left like 3mb log in like a few hours of running with how often it was printing, restarted the server without changing anything else and it's gone

KCP Connection problem

Hello

There is an ongoing problem with kcp that I know has been reported by others in the past but is still present. If you are using KCP in the game and you submit an update for apple, it will be rejected. Because kcp doesn't work on Apple testers.
If it's any clue, I know they use VPNs.

Mirror: KCP client disconnects if ServerChangeScene takes a lot of time

During ServerChangeScene, server stops to receive any messages.
It is also affect for ping\pong messages.

Is scene is big enough it could take more than 10 seconds to load and all clients
with KCP transport disconnect because of checking this timeout.

The behavior could be easily emulated by adding following code
System.Threading.Thread.Sleep(15000);
at the beginning of FinishLoadScene method of NetworkManager.

[https://github.com/MirrorNetworking/Mirror/issues/2480]

original kcp

i apply kcp2k old ver in unity, and use the netty kcp on server
but throw ex when i upgrade the kcp to 1.19
i found out the message add header
is there any way to fix the original kcp?

Segment Pool Sharing

Currently, the segment pool is static and therefore used by all KCP instances. This is a problem when using multiple KCP clients (e.g. for benchmarking) within the same program concurrently.

From what I understand there are two solutions to the problem:

  1. Giving each KCP instance its own Segment Stack
  2. Use ConcurrentStack<Segment> for the pool.

I went with version two for my benchmark test (see JohannesDeml/NetworkBenchmarkDotNet@47ec6b5), since it was an easy change. However, giving each kcp its own pool might be more performant.

Other than the segment pool, the library seems to work fine with a concurrent benchmark setup. Is it in the interest of the maintainers to support multiple KCP instances running at the same time? And if so, which version do you prefer. I think both versions are quite easy to implement and I could provide a PR for it.

jagatai high latency compared to telepathy

  • ummorpg remastered
  • US server
    "i use my actual project based on uMMORPG RE, server is hosted in NYC i live in Florida normal avg ping RTT is 55ms, ingame NetworkTime.RTT with KCP avgs 130-150ms while when i use Telepathy it hovers around 60-70ms"

how to safely throw the packet in kcp snd_buff & snd_queue on kcp server side

i am developing a multiplayer online game, and the real-time requirements are very high. If multiple retransmissions have not been successful, it is meaningless to send the data again. It is hoped that the untransmitted data can be directly discarded when the number of retransmissions reaches a certain threshold (xmit).

packet with small size thows exception

from mirror discord kcp channel

QUOTE:

I found a small malfunction, when a packet whose size is less than 5 byte arrives from the network, an error is generated 
( ArgumentOutOfRangeException: Non-negative number required. ) 
Line 622 (KcpPeer.RawInput)

I wrote a packet size check that fixed this

ArraySegment<byte> message;

if (segment.Count >= (1 + 4)) 
    message = new ArraySegment<byte>(segment.Array, segment.Offset + 1 + 4, segment.Count - 1 - 4);
else return;

END QUOTE

video:
https://discord.com/channels/343440455738064897/765851036417654784/1112822458811174973

Unreliable NetworkPingMessage Kicks Non-Authenticated Client

If a Network Authenticator is implemented, authentication can take several frames, or even seconds, or even minutes depending on complexity (e.g. account creation, character selection, etc.).

Kcp Transport invokes NetworkClient.OnConnected immediately, which calls NetworkTime.UpdateClient:

NetworkTime.cs

internal static void UpdateClient()
{
    if (Time.time - lastPingTime >= PingFrequency)
    {
        NetworkPingMessage pingMessage = new NetworkPingMessage(LocalTime());
        NetworkClient.Send(pingMessage, Channels.DefaultUnreliable);
        lastPingTime = Time.time;
    }
}

Server kicks the connection because NetworkPingMessage gets to server before Authentication has completed and server still has that connection in KcpState.Connected, logging this on server:

KCP: received unreliable message in state Connected. Disconnecting the connection.
UnityEngine.Debug:LogWarning(Object)
kcp2k.KcpConnection:RawInput(Byte[], Int32) (at Assets/Mirror/Runtime/Transport/KCP/kcp2k/highlevel/KcpConnection.cs:447)
kcp2k.KcpServer:Tick() (at Assets/Mirror/Runtime/Transport/KCP/kcp2k/highlevel/KcpServer.cs:206)
kcp2k.KcpTransport:LateUpdate() (at Assets/Mirror/Runtime/Transport/KCP/MirrorTransport/KcpTransport.cs:125)

Bottom Line
It's not Kcp's role to be draconian here. Mirror will deal with inappropriate messages. Kcp needs to just pass the message through and not worry about it.

Crash on Ubuntu 20.04

When trying to run a dedicated server on Ubuntu 20.04 I keep getting this error:

NullReferenceException: Object reference not set to an instance of an object
  at kcp2k.KcpTransport.ServerStart () [0x00000] in <3f58c2d5ab6045e99072d494f8577adc>:0
  at Mirror.NetworkServer.Listen (System.Int32 maxConns) [0x00012] in <3f58c2d5ab6045e99072d494f8577adc>:0
  at Mirror.NetworkManager.SetupServer () [0x00066] in <3f58c2d5ab6045e99072d494f8577adc>:0
  at Mirror.NetworkManager.StartServer () [0x00019] in <3f58c2d5ab6045e99072d494f8577adc>:0
  at Mirror.NetworkManager.Start () [0x00008] in <3f58c2d5ab6045e99072d494f8577adc>:0

Steps to reproduce:

  • Create a mirror project using Kcp Transport or clone this test repository
  • Build it with IL2CPP
  • Run on Ubuntu version 20.04

What fixed for me

To not get the error I had to run it on an older version of ubuntu (18.04).

Throw an error when switching networks. But why hasn't ping been working

Error: System.Net.Sockets.SocketException (0x80004005): Network is unreachable
at System.Net.Sockets.Socket.Send (System.Byte[] buffer, System.Int32 offset, System.Int32 size, System.Net.Sockets.SocketFlags socketFlags) [0x00000] in <00000000000000000000000000000000>:0
at System.Threading.ExecutionContext.RunInternal (System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, System.Object state, System.Boolean preserveSyncCtx) [0x00000] in <00000000000000000000000000000000>:0
at Fantasy.KCPClientNetwork.Output (System.Byte[] bytes, System.Int32 count) [0x00000] in <00000000000000000000000000000000>:0
at kcp2k.Kcp.FlushBuffer (System.Int32 size) [0x00000] in <00000000000000000000000000000000>:0
at kcp2k.Kcp.Flush () [0x00000] in <00000000000000000000000000000000>:0
at kcp2k.Kcp.Update (System.UInt32 currentTimeMilliSeconds) [0x00000] in <00000000000000000000000000000000>:0
at Fantasy.KCPClientNetwork.KcpUpdate () [0x00000] in <00000000000000000000000000000000>:0
at Fantasy.KCPClientNetwork.Update () [0x00000] in <00000000000000000000000000000000>:0
at Fantasy.NetworkThread.Update () [0x00000] in <00000000000000000000000000000000>:0

System.Threading.ExecutionContext:RunInternal(ExecutionContext, ContextCallback, Object, Boolean)
Fantasy.UnityLog:Error(String)
Fantasy.Log:Error(Exception)
Fantasy.KCPClientNetwork:Output(Byte[], Int32)
kcp2k.Kcp:FlushBuffer(Int32)
kcp2k.Kcp:Flush()
kcp2k.Kcp:Update(UInt32)
Fantasy.KCPClientNetwork:KcpUpdate()
Fantasy.KCPClientNetwork:Update()
Fantasy.NetworkThread:Update()

Can you provide a c# server code alone?I plan to use it to synchronize data between multiple clients.

Can you provide a c# server code alone, which is not Unity, so that I can learn easily. I plan to use it to synchronize data between multiple clients.
Task.Run(() => {

             while (true)
             {
                 server.Tick();
                //TickIncoming();
                //TickOutgoing();
             }
         });

Is such code ok? If you put it into c# to run alone, please give pointers on what to optimize.

Using kcp for the first time, some problems need your help. Please give pointers! sincere thanks!

client will disconnect immediately after connect to the server?

The server is running and Broadcasting unreliable message to all connected clients in update function. At this time, any other new client can not connect to this server.
The log shows as below:
============log info=============
KcpClient: connect to 172.xxx.xxx.xxx:7777
KcpConnection: sending Handshake to other end!
KCP: received unreliable message in state Connected. Disconnecting the connection.
KCP Connection: Disconnected.
KCP: OnClientDisconnected

it seems that the code in KcpConnection.cs call the Disconnect() function. [the last line below]

` if (state == KcpState.Authenticated)
{
// only process messages while not paused for Mirror
// scene switching etc.
// -> if an unreliable message comes in while
// paused, simply drop it. it's unreliable!
if (!paused)
{
ArraySegment message = new ArraySegment(buffer, 1, msgLength - 1);
OnData?.Invoke(message);
}

                        // set last receive time to avoid timeout.
                        // -> we do this in ANY case even if not enabled.
                        //    a message is a message.
                        // -> we set last receive time for both reliable and
                        //    unreliable messages. both count.
                        //    otherwise a connection might time out even
                        //    though unreliable were received, but no
                        //    reliable was received.
                        lastReceiveTime = (uint)refTime.ElapsedMilliseconds;
                    }
                    else
                    {
                        // should never
                        Log.Warning($"KCP: received unreliable message in state {state}. Disconnecting the connection.");
                        Disconnect();
                    }`

NetworkTransformReliable doesn't work with KCP Transport

When new player joins and moves, only the old player will see the update, but if old player moves, the new player won't see update.

Steps to reproduce:

  1. Make a new Unity project (Unity 2021.3.21f1)
  2. Add Mirror (Mirror-78.4.3)
  3. Make a Manager Game Object with NetworkManager, NetworkManagerHUD, and KcpTransport and assign it to NetworkManager
  4. Make player game object with simple Movement script
  5. Add NetworkTransformReliable to player object and select SyncDirection to ClientToServer.
  6. Turn that player into prefab and assign it to NetworkManager, remove it from scene and build the game
  7. Play and move on host and on client to see the issue

Stream mode

Hello, is KCP stream mode available in this library?

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.