zestylife / EuNet

Peer to peer network solution for multiplayer games.
MIT License
142 stars 26 forks source link

NullReferenceException on P2pTest.cs / P2pTest에서 오류 발생 #9

Open MineEric64 opened 1 year ago

MineEric64 commented 1 year ago

안녕하세요, 개발자가 한국인이길래 이슈도 한국어로 해도 괜찮은거겠죠?

아무튼 P2pTest.cs 에서 테스트를 해보면 image 이렇게 정상적으로 테스트가 성공되지만,

제가 직접 코드를 복붙해보고 저의 프로젝트에 적용해보면 (WPF, Net Framework 4.8) image TcpListener.cs에서 NullReferenceException 오류가 나면서 P2P 테스트가 되질 않습니다.

참고로 DLL은 EuNet 프로젝트를 빌드하고 복사해서 프로젝트에 적용했습니다.

코드는 Assert 부분 빼고 완벽하게 복붙해서 코드 부분은 걱정하지 않아도 될 것 같습니다. 혹시 모르니 코드 부분도 첨부하도록 하겠습니다.

private P2pGroup _p2pGroup;

        public async Task Test(
            int clientCount,
            int sendCount)
        {
            var serverTcs = new TaskCompletionSource<string>();
            int receivedUnreliableCount = 0;
            int receivedTcpCount = 0;

            NetServer server = new NetServer(
                new ServerOption()
                {
                    Name = "TestServer",
                    TcpServerPort = 9000,
                    IsServiceUdp = true,
                    UdpServerPort = 9001,
                    TcpBackLog = Math.Max(clientCount, 512),
                    MaxSession = clientCount,
                });

            server.OnSessionReceived += (ISession session, NetDataReader reader) =>
            {
                var text = reader.ReadString();

                var writer = NetPool.DataWriterPool.Alloc();
                try
                {
                    if (text == "Join")
                    {
                        var result = _p2pGroup.Join(session as ServerSession);

                        Console.WriteLine($"P2p joined {result}");
                    }
                    else if (text == "Leave")
                    {
                        var result = _p2pGroup.Leave(session as ServerSession);

                        Console.WriteLine($"P2p leaved {result}");
                    }
                    else if (text == "Unreliable")
                    {
                        Interlocked.Increment(ref receivedUnreliableCount);

                        writer.Write("Unreliable");

                        session.SendAsync(writer, DeliveryMethod.Unreliable);
                    }
                    else
                    {
                        Interlocked.Increment(ref receivedTcpCount);

                        if (text == "Finish")
                        {
                            writer.Write("Finish");
                        }
                        else writer.Write($"Hello Client{session.SessionId}");

                        session.SendAsync(writer, DeliveryMethod.Tcp);
                    }
                }
                finally
                {
                    NetPool.DataWriterPool.Free(writer);
                }

                return Task.CompletedTask;
            };

            server.OnSessionErrored += (ISession session, Exception ex) =>
            {
                serverTcs.TrySetException(ex);
            };

            await server.StartAsync();

            _p2pGroup = server.P2pManager.CreateP2pGroup();

            List<Task<NetClient>> taskList = new List<Task<NetClient>>();
            for (int i = 0; i < clientCount; i++)
            {
                taskList.Add(WorkClient(i, sendCount));
            }

            await Task.WhenAny(Task.WhenAll(taskList), serverTcs.Task);

            foreach (var task in taskList)
                task.Result.Close();

            await Task.Delay(1000);

            await server.StopAsync();

            await Task.Delay(1000);

            Console.WriteLine($"Server receivedTcpCount : {receivedTcpCount}");
            Console.WriteLine($"Server receivedUnreliableCount : {receivedUnreliableCount}");

            //NetPool.PacketPool은 internal 속성이므로 제외

            Console.WriteLine("****** DataWriterPool ******");
            Console.WriteLine(NetPool.DataWriterPool.ToString());
            Console.WriteLine("");
        }

        private async Task<NetClient> WorkClient(int index, int sendCount)
        {
            NetClient client = new NetClient(new ClientOption()
            {
                TcpServerAddress = "127.0.0.1",
                TcpServerPort = 9000,
                IsServiceUdp = true,
                UdpServerAddress = "127.0.0.1",
                UdpServerPort = 9001
            });

            int receivedUnreliableCount = 0;
            int receivedP2pCount = 0;
            var tcs = new TaskCompletionSource<string>();

            client.OnReceived += (NetDataReader reader) =>
            {
                string text = reader.ReadString();

                if (text == "Finish")
                    tcs.SetResult(text);
                else if (text == "Unreliable")
                {
                    receivedUnreliableCount++;
                }
                else
                {

                }

                return Task.CompletedTask;
            };

            client.OnP2pReceived += (ISession session, NetDataReader reader) =>
            {
                string text = reader.ReadString();
                //Console.WriteLine($"------------- {text}");
                receivedP2pCount++;

                return Task.CompletedTask;
            };

            client.OnErrored += (e) =>
            {
                tcs.SetException(e);
            };

            client.OnClosed += () =>
            {
                //tcs.SetException(new Exception("session closed"));
                tcs.TrySetException(new Exception("session closed"));
            };

            Task.Factory.StartNew(async () =>
            {
                await Task.Delay(100);
                Stopwatch sw = Stopwatch.StartNew();
                while (client.State != SessionState.Closed)
                {
                    sw.Stop();
                    client.Update((int)sw.ElapsedMilliseconds);
                    sw.Restart();
                    await Task.Delay(30);
                }
            }).DoNotAwait();

            var connected = await client.ConnectAsync(null); //여기서 NullReferenceException 발생

            var writer = NetPool.DataWriterPool.Alloc();
            try
            {
                writer.Write("Join");
                client.SendAsync(writer, DeliveryMethod.Tcp);
            }
            finally
            {
                NetPool.DataWriterPool.Free(writer);
            }

            await Task.Delay(3000);

            writer = NetPool.DataWriterPool.Alloc();
            try
            {
                writer.Write($"P2pReliableOrdered {client.SessionId}");
                client.P2pGroup.SendAll(writer, DeliveryMethod.ReliableOrdered);
            }
            finally
            {
                NetPool.DataWriterPool.Free(writer);
            }

            writer = NetPool.DataWriterPool.Alloc();
            try
            {
                writer.Write($"P2pUnreliable {client.SessionId}");
                client.P2pGroup.SendAll(writer, DeliveryMethod.Unreliable);
            }
            finally
            {
                NetPool.DataWriterPool.Free(writer);
            }

            await Task.Delay(1000);

            if (index % 10 != 1)
            {
                writer = NetPool.DataWriterPool.Alloc();
                try
                {
                    writer.Write("Leave");
                    client.SendAsync(writer, DeliveryMethod.Tcp);
                }
                finally
                {
                    NetPool.DataWriterPool.Free(writer);
                }

                await Task.Delay(1000);
            }

            writer = NetPool.DataWriterPool.Alloc();
            try
            {
                writer.Write("Finish");
                client.SendAsync(writer, DeliveryMethod.Tcp);
            }
            finally
            {
                NetPool.DataWriterPool.Free(writer);
            }

            /*for (int i = 0; i < sendCount; i++)
            {
                writer = NetPool.DataWriterPool.Alloc();
                try
                {
                    if (i < sendCount - 1)
                        writer.Put("Hello Server");
                    else writer.Put("Finish");

                    client.SendAsync(writer, DeliveryMethod.Tcp);
                }
                finally
                {
                    NetPool.DataWriterPool.Free(writer);
                }

                writer = NetPool.DataWriterPool.Alloc();
                try
                {
                    writer.Put("Unreliable");

                    client.SendAsync(writer, DeliveryMethod.Unreliable);
                }
                finally
                {
                    NetPool.DataWriterPool.Free(writer);
                }
            }*/

            await Task.Delay(1000);

            await tcs.Task;

            Console.WriteLine($"receivedUnreliableCount : {receivedUnreliableCount}");

            return client;
        }

        private async void xProdigy_Click(object sender, RoutedEventArgs e)
        {
            await Test(3, 1);
            MessageBox.Show("hurary!");
        }

감사합니다.

playg8 commented 1 year ago

Got it!