RevenantX / LiteNetLib

Lite reliable UDP library for Mono and .NET
https://revenantx.github.io/LiteNetLib/index.html
MIT License
3k stars 489 forks source link

.net8 with bug cannot send msg #552

Open ashyEmmm opened 3 weeks ago

ashyEmmm commented 3 weeks ago

In .net8, when I send messages to Unity, I can only trigger the NetworkReceiveEvent event of Unity, but there is no such bug in. net6

//Some c# code if needed
//.net8
serverPeer.Send(writer, DeliveryMethod.ReliableOrdered)
//unity
listener.ConnectionRequestEvent += request =>
{
    Debug.Log("aaaa");
    request.Accept();
};
//output
//aaaa

Library version: [release version (1.2.0)]

Framework: [Mono, Unity, dotnetcore, .NET Framework]

OS: [Windows]

RevenantX commented 3 weeks ago

@ashyEmmm how you can trigger NetworkReceiveEvent without ConnectRequest and Connected events?

ashyEmmm commented 3 weeks ago

this full code,if I switch from. net8 to. net6, then everything is normal. .net8 code

 public partial class Form1 : Form
    {
        static int port = 0;
        NetManager netManager;
        NetPeer serverPeer;
        Thread thread;
        public Form1()
        {
            port = int.Parse(Environment.GetCommandLineArgs()[1]);

            EventBasedNetListener listener = new EventBasedNetListener();
            netManager = new NetManager(listener);
            listener.NetworkReceiveEvent += Listener_NetworkReceiveEvent;
            netManager.Start();
            serverPeer = netManager.Connect("127.0.0.1", port, "");

            thread = new Thread(() =>
            {
                while (true) {
                    netManager.PollEvents();
                    try
                    {
                        Thread.Sleep(15);
                    }
                    catch (ThreadInterruptedException ex)
                    {
                        break;
                    }
                }
            });
            thread.Start();

            InitializeComponent();
        }

        private void Listener_NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
        {
            var cmd = reader.GetString();
            if (cmd == "Quit")
            {
                Application.Exit();
            }
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            base.WindowState = FormWindowState.Minimized;
            base.Visible = false;
        }

        private void 退出ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            SendData("Quit");
            Thread.Sleep(5000);
            thread?.Interrupt();
            serverPeer.Disconnect();
            Thread.Sleep(100);
            Application.Exit();
        }

        private void SendData(string msg)
        {
            NetDataWriter writer = new NetDataWriter();         // Create writer class
            writer.Put(msg);                        // Put some string
            serverPeer.Send(writer, DeliveryMethod.ReliableOrdered);  // Send with reliability
        }
    }

unity code.The public methods of this class will be called elsewhere

    public class WindowsMsg
    {
        NetManager netManager;
        HashSet<NetPeer> netPeers = new HashSet<NetPeer>();

        public void Start()
        {
            EventBasedNetListener listener = new EventBasedNetListener();
            netManager = new NetManager(listener);
            netManager.Start("localhost", "0:0:0:0:0:0:0:1",0);
            listener.ConnectionRequestEvent += request =>
            {
                Debug.Log("AAAA");
                var p = request.Accept();
                netPeers.Add(p);
            };

            listener.NetworkReceiveEvent += Listener_NetworkReceiveEvent;
            listener.PeerDisconnectedEvent += Listener_PeerDisconnectedEvent;

            Debug.Log(netManager.LocalPort);
            ProcessStartInfo processStartInfo = new ProcessStartInfo()
            {
                FileName = Application.streamingAssetsPath+ "/exsoft/AutoPetTaskIcon.exe",
                CreateNoWindow = true,
                Arguments = netManager.LocalPort.ToString(),
            };
            Process process = Process.Start(processStartInfo);

        }

        private void Listener_PeerDisconnectedEvent(NetPeer peer, DisconnectInfo disconnectInfo)
        {
            if (netPeers.Contains(peer))
            {
                netPeers.Remove(peer);
            }
        }

        private void Listener_NetworkReceiveEvent(NetPeer peer, NetPacketReader reader, byte channel, DeliveryMethod deliveryMethod)
        {
            var cmd = reader.GetString();
            if (cmd == "Quit")
            {
                Application.Quit();
                UnityEngine.Debug.Log("QUIT");
            }
        }

        public void Dispose()
        {
            netManager.Stop();
            foreach (NetPeer peer in netPeers)
            {
                NetDataWriter writer = new NetDataWriter();         // Create writer class
                writer.Put("Quit");                        // Put some string
                peer.Send(writer, DeliveryMethod.ReliableOrdered);  // Send with reliability
            }
        }

        public void Update()
        {
            netManager.PollEvents();
        }
    }
RevenantX commented 3 weeks ago

@ashyEmmm well you bound only receive event. Better use INetEventListener and implement all methods in it like in unity example here https://github.com/RevenantX/LiteNetLib/blob/master/LiteNetLibSampleUnity/Assets/GameServer.cs

Also in your case in WinForm you can use NetManager.UnsyncedEvents - in this case you don't need to spawn update thread. PollEvents will be called from library thread automatically. But remember that you will need use ConcurrentCollections or lock/etc synchronization between threads

Also i don't see whats wrong. Can you write .net6 output and expected behaviour and .net8. Also add logs to every event

ashyEmmm commented 3 weeks ago

@RevenantX When the beginning net8,unity output is AAAA net6,unity output is AAAA When sending "Quit" net8: unity output is AAAA net6: unity output is Quit

Net8 should be like Net6

RevenantX commented 3 weeks ago

@ashyEmmm can you include minimal example project with bug?

I tried your case in .net8 and cannot reproduce this

ashyEmmm commented 3 weeks ago

@RevenantX Yes, I have also tried Net8 and it is not a problem.
I found out that I am actually using net8-windows, which is WinForms.
There is an error in the WinForms, and I have a screenshot to show it.
When creating the minimum example project, I found that the problem was caused by me fixing the error message

I also included a minimum example project 84f37dca-0b7e-46b3-9775-15fafc430993

MiniUnitWinForms.zip

And I found out that it actually triggered the reconnection behavior

QQ截图20240607121609