Toemsel / Network

C# Network Library
https://push-force.dev
GNU Lesser General Public License v3.0
355 stars 65 forks source link

WritePacketThreadException with Unity build on android #78

Closed JeffreyR-1746919 closed 3 years ago

JeffreyR-1746919 commented 3 years ago

Library works as it should when 2 unity instances are running in the editor, one is the server, the other the client. But when I build the client to my android phone, the client succesfully connects to the server, but then after a while the server shows the client closed the connection with reason: Timeout. No packet that is sent after the tcp connection is established ever arrives at the server. Debugging with ADB reveals that the client errors out with a WritePacketThreadException.

Toemsel commented 3 years ago

Look at the inner exception. That error indicates an error on your side. Basically the lib cant serialize your object. Either a type isn't supported or you do something during the serialization. Are on both sides the packet assemblies known?

JeffreyR-1746919 commented 3 years ago

I forgot to mention that it's just the close reason of the client that says WritePacketThreadException. The error happens in the library i guess which i'm unable to get. Also I just commented out all of the sending of packets, and the connection still closes with this reason. The only thing it does is create a TCP connection.

Toemsel commented 3 years ago

Can you share the project? Alternative is to enable logging and read the output.

JeffreyR-1746919 commented 3 years ago

Can't manage to get logging to work on android build, running on phone. Server log prints some errors: SERVER_LOG.txt

The code is nothing special, just a client that creates a TCP connection, and server connection container that starts the tcp listener.

FYI using .NET TcpClient with the same setup (client on android, server on PC) works like a charm.

Tbh I don't have much time at the moment to try and fix this issue, I might switch to just using TcpClient.

Toemsel commented 3 years ago
System.NullReferenceException: Object reference not set to an instance of an object
  at Server.ConnectionLost

Try to set Server.ConnectionLost to a valid instance. However, that wont change anything. I can only guess as there are no relevant logs on the server-side. Only that the client isn't reachable, which you already did describe.

Therefore, my ideas are:

  1. The Server part includes classes the client has no access to (Pay attention to share all libraries to both parties)
  2. You send an object which has unsupported data-types in it
  3. Ensure that the Firewall isn't blocking any traffic (Could be based on your chosen port)
  4. Use the TcpConnection instead of the ClientConnectionContainer, if you do not plan to use UDP at all
  5. If you use the ClientConnectionContainer, ensure that UDP has been enabled on the server-side

I know that is vague, but so is your report. WritePacketThreadException only occurs if the library cant serialize your packet. As the packet is part of you software, we can't do much here. Orient yourself around the provided examples. E.g.: https://github.com/Toemsel/Network/blob/master/Examples/NetworkTestClient/ObjectExample.cs

Good luck

JeffreyR-1746919 commented 3 years ago
  1. This doesn't make any sense since everything works perfectly when I run the app in the unity editor (including sending custom packets) instead of running a build on my phone.
  2. Same as 1. + I'm by the way not even sending any data, the connection just closes.
  3. This also doesn't make any sense, since using TcpClient works, as well as sending data using its NetworkStream.
  4. Already doing that.
  5. See 4.

I managed to get a log from the client side: CLIENT_LOG.txt

Well, thanks for the help anyway, I appreciate the quick response.

Toemsel commented 3 years ago

Ic. Thanks for the clarification.


| TcpConnection | Write object on stream | 192.168.0.142:33844 | System.NullReferenceException: Object reference not set to an instance of an object.
  at System.Linq.Expressions.Interpreter.LightLambda.MakeRunDelegateCtor (System.Type delegateType) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Expressions.Interpreter.LightLambda.GetRunDelegateCtor (System.Type delegateType) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Expressions.Interpreter.LightLambda.MakeDelegate (System.Type delegateType) [0x00000] in <00000000000000000000000000000000>:0 
  at System.Linq.Expressions.Expression`1[TDelegate].Compile (System.Boolean preferInterpretation) [0x00000] in <00000000000000000000000000000000>:0 

I would have to debug into this issue. It seems to happen here https://github.com/Toemsel/Network/blob/4fcf72487cf2dce7c0f0d78fd52109484018202a/Network/Converter/PacketConverter.cs#L146 However, I have no clue which object is null. Can you share the SDK version of you android project? I would like to reproduce this issue. It might also affect other people as well. Also, are you using Unity for Android? Best would be if you just drop the client code, as you already stated it is pretty much empty. I can fake a server. Thats ok

JeffreyR-1746919 commented 3 years ago

No problem.

I use Unity version 2020.3.0f1 with Android Build Support. Minimum API Level is 28, target API level is set to Automatic. Also I use .NET Standard 2.0

The project supports Google Cardboard, so the project settings might have something to do with it. Here is the relevant client code and project settings: files.zip

Toemsel commented 3 years ago

I could reproduce your scenario. It does work within the editor and also while "live-debugging" directly on the android device. However, after deployment to the phone, it crashes after sending the first packet.

In this regards Unity is pretty strange. Their remote debugging (Unity Remote) is actually a streaming service (same accounts for other platforms like Hololens) which streams the Unity rendered on your PC to the phone. Long story short, while being on your PC, a different .NET Framework will be chosen. While executing the Unity project on android, another version of .NET (I am not sure which specific version of Mono that currently is; OR it also could be cross-compiled to CPP - IL2CPP) takes over, which is sadly not 100% compatible with the .NET Standard 2.0 as it seems.

Due to this behaviour I am not even able to debug into the issue. Sadly, you can't use this library on android.

IL2CPP should work fine with any library that works with an AOT platform. If if the library uses dynamic code generation (via System.Reflection.Emit), it won't work with IL2CPP.

The lib uses Reflection, but doesn't use Reflection.Emit. Not sure if that could be an issue, even though he doesn't mention it.

Addon: You could run the app against Mono, instead of IL2CPP. However, ARM devices aren't supported.

Screenshot-2021-05-15-023121.png