コード例 #1
0
        internal void SendUnsentMessages(double now)
        {
            // Add any acknowledges to unsent messages
            if (m_acknowledgesToSend.Count > 0)
            {
                if (m_unsentMessages.Count < 1)
                {
                    // Wait before sending acknowledges?
                    if (m_ackMaxDelayTime > 0.0f)
                    {
                        if (m_ackWithholdingStarted == 0.0)
                        {
                            m_ackWithholdingStarted = now;
                        }
                        else
                        {
                            if (now - m_ackWithholdingStarted < m_ackMaxDelayTime)
                            {
                                return;                                 // don't send (only) acks just yet
                            }
                            // send acks "explicitly" ie. without any other message being sent
                            m_ackWithholdingStarted = 0.0;
                        }
                    }
                }

                // create ack messages and add to m_unsentMessages
                CreateAckMessages();
            }

            if (m_unsentMessages.Count < 1)
            {
                return;
            }

            // throttling
            float throttle     = m_owner.m_config.ThrottleBytesPerSecond;
            float maxSendBytes = float.MaxValue;

            if (throttle > 0)
            {
                double frameLength = now - m_lastSentUnsentMessages;

                //int wasDebt = (int)m_throttleDebt;
                if (m_throttleDebt > 0)
                {
                    m_throttleDebt -= (float)(frameLength * (double)m_owner.m_config.ThrottleBytesPerSecond);
                }
                //int nowDebt = (int)m_throttleDebt;
                //if (nowDebt != wasDebt)
                //	LogWrite("THROTTLE worked off -" + (nowDebt - wasDebt) + " bytes = " + m_throttleDebt);

                m_lastSentUnsentMessages = now;

                maxSendBytes = throttle - m_throttleDebt;
                if (maxSendBytes < 0)
                {
                    return;                     // throttling; no bytes allowed to be sent
                }
            }

            int  mtu           = m_owner.Configuration.MaximumTransmissionUnit;
            bool useCoalescing = m_owner.Configuration.UseMessageCoalescing;

            int       messagesInPacket = 0;
            NetBuffer sendBuffer       = m_owner.m_sendBuffer;

            sendBuffer.Reset();
            while (m_unsentMessages.Count > 0)
            {
                OutgoingNetMessage msg   = m_unsentMessages.Peek();
                int estimatedMessageSize = msg.m_data.LengthBytes + 5;

                // check if this message fits the throttle window
                if (estimatedMessageSize > maxSendBytes)                 // TODO: Allow at last one message if no debt
                {
                    break;
                }

                // need to send packet and start a new one?
                if (messagesInPacket > 0)
                {
                    if (!useCoalescing || (sendBuffer.LengthBytes + estimatedMessageSize > mtu))
                    {
                        m_owner.SendPacket(m_remoteEndPoint);
                        int sendLen = sendBuffer.LengthBytes;
                        m_statistics.CountPacketSent(sendLen);
                        //LogWrite("THROTTLE Send packet +" + sendLen + " bytes = " + m_throttleDebt + " (maxSendBytes " + maxSendBytes + " estimated " + estimatedMessageSize + ")");
                        m_throttleDebt += sendLen;
                        sendBuffer.Reset();
                    }
                }

                if (msg.m_sequenceNumber == -1)
                {
                    AssignSequenceNumber(msg);
                }

                // pop and encode message
                m_unsentMessages.Dequeue();
                int pre = sendBuffer.m_bitLength;
                msg.m_data.m_readPosition = 0;
                msg.Encode(sendBuffer);

                int encLen = (sendBuffer.m_bitLength - pre) / 8;
                m_statistics.CountMessageSent(msg, encLen);
                maxSendBytes -= encLen;

                if (msg.m_sequenceChannel >= NetChannel.ReliableUnordered)
                {
                    // reliable; store message (incl. buffer)
                    msg.m_numSent++;
                    StoreMessage(now, msg);
                }
                else
                {
                    // not reliable, don't store - recycle...
                    NetBuffer b = msg.m_data;
                    b.m_refCount--;

                    msg.m_data = null;

                    // ... unless someone else is using the buffer
                    if (b.m_refCount <= 0)
                    {
                        m_owner.RecycleBuffer(b);
                    }

                    //m_owner.m_messagePool.Push(msg);
                }
                messagesInPacket++;
            }

            // send current packet
            if (messagesInPacket > 0)
            {
                m_owner.SendPacket(m_remoteEndPoint);
                int sendLen = sendBuffer.LengthBytes;
                m_statistics.CountPacketSent(sendLen);
                //LogWrite("THROTTLE Send packet +" + sendLen + " bytes = " + m_throttleDebt);
                m_throttleDebt += sendLen;
            }
        }