public override void SendPacket(ReliableUdpConnectionRecord connectionRecord) { //Debug.WriteLine( "#{0} block sending...", connectionRecord.SndNext ); //RU: отправляем блок пакетов //EN: sending block of packets for (connectionRecord.PacketCounter = 0; connectionRecord.PacketCounter < connectionRecord.WindowSize && connectionRecord.SndNext < connectionRecord.NumberOfPackets; connectionRecord.PacketCounter++) { ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord); ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header)); connectionRecord.SndNext++; } //RU: на случай большого окна передачи, перезапускаем таймер после отправки connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1); if (connectionRecord.CloseWaitTimer != null) { connectionRecord.CloseWaitTimer.Change(-1, -1); } }
public override void SendPacket(ReliableUdpConnectionRecord connectionRecord) { try { System.Threading.Monitor.Enter(connectionRecord.LockerReceive); connectionRecord.PacketCounter = 0; connectionRecord.SndNext = 0; connectionRecord.WindowLowerBound = 0; #region Sending a message that does not require confirmation of delivery (Flags = NoAsk) //RU: если подтверждения не требуется - отправляем все пакеты //RU: и высвобождаем ресурсы //EN: if confirmation of delivery doesn't requires than //EN: send all packets and release the resources if (connectionRecord.IsNoAnswerNeeded) { //RU: Здесь происходит отправка As Is //RU: при такой отправке возможен вариант //RU: кроме того при большой нагрузке возможна потеря первого пакета (не попадание в буфер приема) //RU: соответственно в таком случае все отправленные с данной TransmissionId //RU: пакеты буду отброшены //EN: Here is "As Is" sending //EN: If in some cases first packet won't arrive on endpoint than all packets of the //EN: current TransmissionId will be droped do { connectionRecord.CToken.ThrowIfCancellationRequested(); ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, ReliableUdpStateTools. CreateReliableUdpHeader( connectionRecord) )); connectionRecord.SndNext++; } while (connectionRecord.SndNext < connectionRecord.NumberOfPackets); SetAsCompleted(connectionRecord); return; } #endregion connectionRecord.CToken.ThrowIfCancellationRequested(); ReliableUdpHeader header = ReliableUdpStateTools.CreateReliableUdpHeader(connectionRecord); ReliableUdpStateTools.SendPacket(connectionRecord, ReliableUdpStateTools.CreateUdpPayload(connectionRecord, header)); //RU: увеличиваем счетчик //EN: increase SndNext connectionRecord.SndNext++; //RU: сдвигаем окно //EN: move window lower bound connectionRecord.WindowLowerBound++; connectionRecord.State = connectionRecord.Tcb.States.SendingCycle; //RU: Запускаем таймер //EN: Start the timer connectionRecord.WaitForPacketsTimer = new Timer(CheckByTimer, connectionRecord, connectionRecord.ShortTimerPeriod, -1); } catch (ArgumentNullException ex) { SetAsError(connectionRecord, ex); } catch (ArgumentOutOfRangeException ex) { SetAsError(connectionRecord, ex); } catch (ArgumentException ex) { SetAsError(connectionRecord, ex); } catch (ObjectDisposedException ex) { SetAsError(connectionRecord, ex); } catch (InvalidOperationException ex) { SetAsError(connectionRecord, ex); } catch (System.Net.Sockets.SocketException ex) { SetAsError(connectionRecord, ex); } catch (OperationCanceledException ex) { SetAsError(connectionRecord, ex); } finally { System.Threading.Monitor.Exit(connectionRecord.LockerReceive); } }