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); }
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); }