Native C# TCP Socket APIs have multiple bugs in Unity3D but not native console apps

There seems to be some serious issues when trying to use native C# TCP Sockets in Unity.
NOTE: These bugs do NOT happen with .NET 8 or Mono running in a console app (only Unity3D). The same message processing APIs and libraries etc are used and the same packet stream conditions happen in native apps (as illustrated below).

In short TCP sockets when packets are rapidly sent in order of the same size will end up where the receiver will receive the same packet multiple times for packets of unique data.

Example: Test One, running in Unity:
Sender sends unique packets of 64 bytes

  • Send packet 1
  • Send Packet 2
  • Send Packet 3

Receiver of packets gets these

  • (64 bytes received)
  • Receive packet 1
  • (128 bytes received [both packets in this batch])
  • Receive packet 2 (first part of stream)
  • Receive packet 2 (second part of stream receives packet 2 again even though its suppose to be packet 3)

Example: Test Two, running in Unity:
Sender sends unique packets of 64 bytes

  • Send packet 1 (sleep thread 1 second)
  • Send Packet 2 (sleep thread 1 second)
  • Send Packet 3 (sleep thread 1 second)

Receiver of packets gets these

  • (64 bytes received)
  • Receive packet 1
  • (64 bytes received)
  • Receive packet 2
  • (64 bytes received)
  • Receive packet 3

As I said, I’ve confirmed these conditions with native console apps and it only happens on Unity.

Another bug with TCP seems to be IL2CPP specific. When a client socket disconnects, the server knows its disconnected but the client can never connect again after this. (this does not happen on Mono runtime)

UDP packets seem to work fine on all runtimes. But why are there TCP bugs? Is Unity not using the .NET Standard 2.1 Socket libraries?

Submit a bug report with a repro project if you haven’t already. Posting the issue ID and subsequently assigned issue tracker pages also helps interested parties get involved.

.NET Standard is not something that’s got a specific associated class library implementation. It’s a pseudo-framework, merely a definition of the minimum API surface that must be available in frameworks claiming to implement the standard.

By not using standard libs, I mean Mono or .NET Core libs. Clearly this isn’t the case looking at it more (at least there is more going on here).
I’ll make a simple repo app to report with that includes everything.

You need to be more specific what you mean by packet here. TCP is a streaming protocol. It’s transmitted over IP packets but the protocol itself does not work on the basis of packets. So what is your application level protocol that you’ve implemented on top of TCP/IP?

I once made an example with a simplistic protocol that just sends out the length or a message as a 4 byte integer that is followed by the image data. So I don’t have any packet markers but I work with a packet length. Since TCP is a reliable protocol, not a single byte is lost or out of order. So this works reliable. It also works with multiple Unity clients connected to the same server application. The source code for both, server and client is linked.

If you have a specific issue, you need to share at least some insight into your application level protocol. Maybe you made a mistake there?

So can you provide a minimalstic repo case?

1 Like

I was pretty specific. Look at the detailed description of this after. Packets in the context of TCP streams is data blobs you receive in chunks and TCP isn’t void of packet information (this is part of the protocall). This is not about bytes being out of order, its about receiving old data as if its new data with async TCP sockets. Again this works perfect outside Unity3D.

I will post a repo case shortly.

1 Like

I don’t understand your issue here. The way you detailed the arrival of the packets only indicates that the packets are received as expected. Whether packets 2 and 3 arrive in the same “update” does not and should not matter. This can happen at any time for numerous circumstances and may be affected by how these packets get routed across the Internet.

You did test sending them across the Internet, relayed through a different machine? Because if you do so I bet you will notice the behaviour changes every time you run the tests in both cases.

And it could be a simple matter of timing where Unity will send/receive only at discrete steps in an Update cycle, which is framerate dependent, whereas a .NET console application runs a send/receive loop exactly the way you programmed it.

Please do not send bug reports for this because this behavioural difference has a simple explanation, and the end result is not a bug - the same data is sent and received as expected. And that’s what matters!

Please read OP again, carefully this time. Here’s the relevant snippets, emphasis mine.

Sorry for delay on repo project. Was going to do that this weekend but have to attend a funeral instead.
I’ll get one uploaded when I get back.

No worries, take your time. In the end it’s your problem you want to solve :slight_smile:

This is extremely unlikely as TCP itself as a streaming protocol is 100% reliable. It’s slow but this property is one of the most important one. When you download a 12GB file it’s absolutely crucial that every bit of data arrives in the right order and that no data is duplicated. If something is duplicated, I suspect it has to be your buffer handling. Do you by any chance have more than one thread dealing with that buffer? race condition?

ps: Up to this point we don’t even know what classes you actually use. Do you use a TCPClient and a NetworkStream? Or do you use the underlying Socket class manually? There are many things that could go wrong depending on how they are used.

Ok found the issue. So it turns out this isn’t a bug with Unity (thank god) and me trying to optimize some memory copies in my internal code using unsafe code + closures reading old memory later.

Here is the repo tester proj for those interested: GitHub - zezba9000/Unity3D-Socket-BugTester: Used to check for bugs in Unity's C# socket APIs that don't exist in CoreCLR or Mono environments.

Everything is working correctly in my main project now. Test proj told me to look at some logic my brain was just skipping over before.

1 Like

Ok well there still is a bug with IL2CPP. Where something in sockets will not re-connect after intestinal disconnections. And this is 100% for sure different from Mono build or other runtimes etc. Just tested with repo case and it happens with basic test.

Submitted bug report for this: CASE IN-83785