korlibs / korge

KorGE Game Engine. Multiplatform Kotlin Game Engine
https://korge.org/
Other
2.41k stars 122 forks source link

Request: Support TCP Low Latency mode for TCP sockets. Also support QUICK ACK for TCP sockets. #2127

Open 0megaD opened 5 months ago

0megaD commented 5 months ago

Introduction

When supporting networking in an application, we normally have the choice between TCP and UDP connections. TCP is more reliable, but slower, and has some algorithms that try to manage how packets are sent to optimize the bandwidth usage / network congestion. UDP is faster, but less reliable as it does not guarantee that packets are received by the other party.

For cases where UDP is not an option, but where TCP's default algorithms cause too much delay in data traffic, several features and algorithms can be disabled to speed up the sending of TCP packets. Two of these examples are: TCP_NODELAY (aka "TCP Low Latency" mode) TCP_QUICKACK (aka "TCP No Delayed Ack")

KorGE currently lacks methods to manage these modes in "common" code.

Suggestion

Add a parameter or method to allow enabling/disabling of 'low latency mode' and 'delayed ack' on TCP connections, either in the constructor or as a separate method (or both).

I don't know what methods Kotlin currently uses to map to platform specific socket implementations, but here are some examples of how to set this setting on specific platforms.

Documentation Examples

Kotlin JVM (TCP Quick Ack) Kotlin JVM (TCP Low Latency): socket.setTcpNoDelay(bool: Boolean)

Kotlin Android: socket.setTcpNoDelay(bool: Boolean)

iOS (Swift):

let tcp = NWProtocolTCP.Options.init()
tcp.noDelay = true

C (Native Platforms):

int i = 1;
setsockopt( iSock, IPPROTO_TCP, TCP_NODELAY, (void *)&i, sizeof(i));
setsockopt( iSock, IPPROTO_TCP, TCP_QUICKACK, (void *)&i, sizeof(i));

Limitations

JavaScript does not support a 'setTCPNoDelay' option on the 'client-side' (browser) However, it seems like some browsers already disable this option by default (eg.: Chrome)

Alternatively, someone suggested this workaround that seems to work (but does double bandwidth usage)

soywiz commented 5 months ago

Awesome. Thanks for the investigation and for all the details documenting it. Could you consider making a PR?

I guess it could be adding a boolean flag here with a default implementation: https://github.com/korlibs/korge/blob/2b01e2f064408324a6a8fcd6569911eb4b1bdac2/korge-core/src/korlibs/io/net/AsyncSocketFactory.kt#L35 and then implementing it as required: JVM/Android, Native etc.

0megaD commented 5 months ago

Is there a guide or template anywhere to help easily set up an environment where I can build and test an implementation?

I know how to fork/clone a repo and use git etc. but I'm not sure how to hook this up to KorGE (or custom project) as a dependency easily with all the extra platform specific sourcesets and stuff.

soywiz commented 5 months ago

Is there a guide or template anywhere to help easily set up an environment where I can build and test an implementation?

I know how to fork/clone a repo and use git etc. but I'm not sure how to hook this up to KorGE (or custom project) as a dependency easily with all the extra platform specific sourcesets and stuff.

Just moved and updated the contributing section:

https://docs.korge.org/contributing/

Please, let me know if those instructions work for you or you find any kind of problem, or missing things.

Summarizing: You can add the functionality, and then use korge-sandbox to test it, automated tests, or publish it locally and use it using 999.0.0.999 as the version and use it in another project.