Esempio n. 1
0
        //* Usado para enviar os dados para o servidor.
        //* Client->Server
        protected void Send(NeutronStream stream, Protocol protocol = Protocol.Tcp)
        {
            try
            {
                if (IsServer)
                {
                    throw new NeutronException("To use this packet on the server side it is necessary to assign the \"Player\" parameter.");
                }
#if !UNITY_SERVER || UNITY_EDITOR
                if (This.IsConnected)
                {
                    NeutronStream.IWriter wHeader = stream.hWriter;
                    NeutronStream.IWriter wPacket = stream.Writer;
                    byte[] pBuffer = wPacket.ToArray().Compress(); //! Otimizado para evitar alocações, bom isso depende de como você usa o Neutron :p
                    switch (protocol)
                    {
                    //* ValueTask ainda não funciona na Unity, isso mesmo, em 2021 com .net 6 e standard 2.1, e a unity atrasada com essa merda de Mono, vê se pode?
                    case Protocol.Tcp:
                    {
                        if (wHeader.GetPosition() == 0)
                        {
                            wHeader.WriteByteArrayWithAutoSize(pBuffer);         //* Pre-fixa o tamanho da mensagem no cabeçalho, um inteiro/short/byte(4/2/1 bytes), e a mensagem.
                            byte[] hBuffer = wHeader.ToArray();
                            wHeader.Write();

                            NetworkStream networkStream = TcpClient.GetStream();
                            switch (Helper.GetConstants().SendModel)
                            {
                            case SendType.Synchronous:
                                networkStream.Write(hBuffer, 0, hBuffer.Length);             //* Envia os dados pro servidor de modo síncrono, esta opção é melhor, não aloca e tem performance de CPU.
                                break;

                            default:
                                if (Helper.GetConstants().SendAsyncPattern == AsynchronousType.APM)
                                {
                                    networkStream.Write(hBuffer, 0, hBuffer.Length);             //* Envia os dados pro servidor de modo assíncrono, mentira, envia da mesma forma de "SendType.Synchronous", preguiça mesmo. :p, porque BeginReceive e Endreceive é chato de fazer pro TCP :D
                                }
                                else
                                {
                                    SocketHelper.SendTcpAsync(networkStream, hBuffer, TokenSource.Token);             //* Envia os dados pro servidor de forma assíncrona., faz alocações pra caralho, no tcp não tanto, mas no UDP..... é foda. e usa muita cpu, evite, se souber como resolver, sinta-se a vontade para contribuir.
                                }
                                break;
                            }
                            //* Adiciona no profiler a quantidade de dados de saída(Outgoing).
                            NeutronStatistics.ClientTCP.AddOutgoing(hBuffer.Length);
                        }
                        else
                        {
                            throw new Exception($"Send(Tcp): Invalid position, is not zero! Pos -> {wHeader.GetPosition()} Capacity -> {wHeader.GetCapacity()}. You called Finish() ?");
                        }
                    }
                    break;

                    case Protocol.Udp:
                    {
                        if (UdpEndPoint == null)
                        {
                            LogHelper.Error("Unauthenticated!");
                        }
                        else
                        {
                            StateObject.SendDatagram = pBuffer;
                            switch (Helper.GetConstants().SendModel)
                            {
                            case SendType.Synchronous:
                                SocketHelper.SendBytes(UdpClient, pBuffer, UdpEndPoint);             //* envia de modo síncrono, evita alocações e performance boa.
                                break;

                            default:
                            {
                                switch (Helper.GetConstants().SendAsyncPattern)
                                {
                                case AsynchronousType.APM:
                                {
                                    //* aloca, mas não tanto, boa performance.
                                    SocketHelper.BeginSendBytes(UdpClient, pBuffer, UdpEndPoint, (ar) =>
                                                {
                                                    SocketHelper.EndSendBytes(UdpClient, ar);
                                                });
                                    break;
                                }

                                default:
                                    SocketHelper.SendUdpAsync(UdpClient, StateObject, UdpEndPoint);                     //* se foder, aloca pra caralho e usa cpu como a unreal engine, ValueTask poderia resolver, mas......
                                    break;
                                }
                                break;
                            }
                            }
                            //* Adiciona no profiler a quantidade de dados de saída(Outgoing).
                            NeutronStatistics.ClientUDP.AddOutgoing(pBuffer.Length);
                        }
                    }
                    break;
                    }
                }
                else
                {
                    LogHelper.Error("Non-connected socket, sending failed!");
                }
#else
                throw new Exception("To use this packet on the server side it is necessary to assign the \"Player\" parameter.");
#endif
            }
            catch (ObjectDisposedException) { }
            catch (SocketException) { }
            catch (Exception ex)
            {
                LogHelper.Stacktrace(ex);
            }
        }