示例#1
0
        private void SendInternal(
            byte[] data,
            int start,
            int length,
            byte channelNumber,
            DeliveryMethod deliveryMethod,
            object userData)
        {
            if (_connectionState == ConnectionState.ShutdownRequested ||
                _connectionState == ConnectionState.Disconnected)
            {
                return;
            }
            if (channelNumber >= _channels.Length)
            {
                return;
            }

            //Select channel
            PacketProperty property;
            BaseChannel    channel;

            if (deliveryMethod == DeliveryMethod.Unreliable)
            {
                property = PacketProperty.Unreliable;
                channel  = _unreliableChannel;
            }
            else
            {
                property = PacketProperty.Channeled;
                channel  = CreateChannel((byte)(channelNumber * 4 + (byte)deliveryMethod));
            }

            //Prepare
            NetDebug.Write("[RS]Packet: " + property);

            //Check fragmentation
            int headerSize = NetPacket.GetHeaderSize(property);
            //Save mtu for multithread
            int mtu = _mtu;

            if (length + headerSize > mtu)
            {
                //if cannot be fragmented
                if (deliveryMethod != DeliveryMethod.ReliableOrdered && deliveryMethod != DeliveryMethod.ReliableUnordered)
                {
                    throw new TooBigPacketException("Unreliable packet size exceeded maximum of " + (mtu - headerSize) + " bytes");
                }

                int packetFullSize = mtu - headerSize;
                int packetDataSize = packetFullSize - NetConstants.FragmentHeaderSize;
                int totalPackets   = length / packetDataSize + (length % packetDataSize == 0 ? 0 : 1);

                NetDebug.Write("FragmentSend:\n" +
                               " MTU: {0}\n" +
                               " headerSize: {1}\n" +
                               " packetFullSize: {2}\n" +
                               " packetDataSize: {3}\n" +
                               " totalPackets: {4}",
                               mtu, headerSize, packetFullSize, packetDataSize, totalPackets);

                if (totalPackets > ushort.MaxValue)
                {
                    throw new TooBigPacketException("Data was split in " + totalPackets + " fragments, which exceeds " + ushort.MaxValue);
                }

                lock (_sendLock)
                {
                    for (ushort partIdx = 0; partIdx < totalPackets; partIdx++)
                    {
                        int sendLength = length > packetDataSize ? packetDataSize : length;

                        NetPacket p = _packetPool.GetPacket(headerSize + sendLength + NetConstants.FragmentHeaderSize);
                        p.Property       = property;
                        p.UserData       = userData;
                        p.FragmentId     = _fragmentId;
                        p.FragmentPart   = partIdx;
                        p.FragmentsTotal = (ushort)totalPackets;
                        p.MarkFragmented();

                        Buffer.BlockCopy(data, partIdx * packetDataSize, p.RawData, NetConstants.FragmentTotalSize, sendLength);
                        channel.AddToQueue(p);

                        length -= sendLength;
                    }
                    _fragmentId++;
                }
                return;
            }

            //Else just send
            NetPacket packet = _packetPool.GetPacket(headerSize + length);

            packet.Property = property;
            Buffer.BlockCopy(data, start, packet.RawData, headerSize, length);
            packet.UserData = userData;
            channel.AddToQueue(packet);
        }