public bool SendPendingPacket()
        {
            if (_reliable && _sendQueue.Count == 0)
            {
                long currentTime    = DateTime.UtcNow.Ticks;
                long packetHoldTime = currentTime - _lastPacketSendTime;
                if (packetHoldTime < _udpChannel.ResendDelay * TimeSpan.TicksPerMillisecond)
                {
                    return(true);
                }

                var packet = _lastPacket;
                if (packet != null)
                {
                    _lastPacketSendTime = currentTime;
                    _udpChannel.SendTo(packet.RawData, 0, packet.Size, UdpChannel.SendMode.Buffered);
                }
            }
            else
            {
                lock (_sendQueue)
                {
                    while (_sendQueue.Count > 0)
                    {
                        NetPacket packet = _sendQueue.Dequeue();
                        _localSequence  = (_localSequence + 1) % NetPacket.MaxSequence;
                        packet.Sequence = (ushort)_localSequence;

                        _udpChannel.SendTo(packet.RawData, 0, packet.Size, UdpChannel.SendMode.Buffered);

                        if (_reliable && _sendQueue.Count == 0)
                        {
                            _lastPacketSendTime = DateTime.UtcNow.Ticks;
                            _lastPacket         = packet;
                        }
                        else
                        {
                            NetPool.PacketPool.Free(packet);
                        }
                    }
                }
            }

            if (_reliable && _mustSendAck)
            {
                _mustSendAck        = false;
                _ackPacket.Sequence = _remoteSequence;

                _udpChannel.SendTo(_ackPacket.RawData, 0, _ackPacket.Size, UdpChannel.SendMode.Buffered);
            }

            return(true);
        }
        public bool TrySend(long currentTime, int disconnectTimeoutMs, UdpChannel udpChannel, NetStatistic statistic)
        {
            if (_packet == null)
            {
                return(true);
            }

            if (_isSent)
            {
                if (currentTime >= _createTime + disconnectTimeoutMs * TimeSpan.TicksPerMillisecond)
                {
                    return(false);
                }

                long resendDelay    = udpChannel.ResendDelay * TimeSpan.TicksPerMillisecond;
                long packetHoldTime = currentTime - _lastSentTime;
                if (packetHoldTime < resendDelay)
                {
                    return(true);
                }

                Interlocked.Increment(ref statistic.UdpResentCount);
            }

            _lastSentTime = currentTime;
            _isSent       = true;

            udpChannel?.SendTo(_packet.RawData, 0, _packet.Size, UdpChannel.SendMode.Buffered);

            return(true);
        }
Beispiel #3
0
        public bool SendPendingPacket()
        {
            // 응답패킷을 보내야 한다면
            if (_sendAcks == true)
            {
                // lock에 비용이 많이드므로 먼저 체크한번 하고 나중에 또 체크하자
                lock (_ackPacket)
                {
                    if (_sendAcks == true)
                    {
                        _sendAcks = false;
                        _udpChannel.SendTo(_ackPacket.RawData, 0, _ackPacket.Size, UdpChannel.SendMode.Buffered);
                    }
                }
            }

            lock (_pendingPackets)
            {
                long nowTicks = DateTime.UtcNow.Ticks;

                lock (_sendQueue)
                {
                    while (_sendQueue.Count > 0)
                    {
                        int relate = NetUtil.RelativeSequenceNumber(_localSequence, _localWindowStart);
                        if (relate >= WindowSize)
                        {
                            break;
                        }

                        NetPacket packet = _sendQueue.Dequeue();

                        packet.Sequence = (ushort)_localSequence;
                        _pendingPackets[_localSequence % WindowSize].Init(packet, nowTicks);
                        _localSequence = (_localSequence + 1) % NetPacket.MaxSequence;
                    }
                }

                for (int pendingSeq = _localWindowStart; pendingSeq != _localSequence; pendingSeq = (pendingSeq + 1) % NetPacket.MaxSequence)
                {
                    if (_pendingPackets[pendingSeq % WindowSize].TrySend(
                            nowTicks,
                            _channelOption.RudpDisconnectTimeout,
                            _udpChannel,
                            _statistic) == false)
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }