예제 #1
0
 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);
     }
 }
예제 #2
0
        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);
            }
        }