Esempio n. 1
0
        /// <summary>
        /// Invokes on timer
        /// </summary>
        /// <param name="connectionRecord"></param>
        /// <returns></returns>
        public override void ProcessPackets(ReliableUdpConnectionRecord connectionRecord)
        {
            try
            {
                System.Threading.Monitor.Enter(connectionRecord.LockerReceive);
                if (connectionRecord.IsDone != 0)
                {
                    return;
                }
                //Debug.WriteLine( "In timer. Means no ask received" );
                //RU: отправляем повторно последний пакет
                //RU: ( в случае восстановления соединения узел-приемник заново отправит запросы, которые до него не дошли)
                //EN: send the last sent message
                //EN: if connection will be established again the recepient will send again all request for lost packets
                ReliableUdpStateTools.SendPacket(connectionRecord,
                                                 ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord,
                                                                                                      connectionRecord.SndNext -
                                                                                                      1));

                //RU: включаем таймер CloseWait
                //EN: start closewait timer
                StartCloseWaitTimer(connectionRecord);
            }
            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);
            }
            finally
            {
                System.Threading.Monitor.Exit(connectionRecord.LockerReceive);
            }
        }
Esempio n. 2
0
        public override void ReceivePacket(ReliableUdpConnectionRecord connectionRecord, ReliableUdpHeader header,
                                           byte[] payload)
        {
            try
            {
                //RU: ПРИМЕЧАНИЯ:
                //RU: важно понимать разницу между подтверждениями о получении
                //RU: и запросами потерянных пакетов.
                //RU: когда отправляем подтверждение, то указываем номер последовательности,
                //RU: которая должна прийти следующей
                //RU: когда отправляем запрос о получении потерянных пакетов
                //RU: то указываем номер той конкретной последовательности которая потерялась
                //EN: NOTES:
                //EN: it is important to understand the difference between the acknowledgment
                //EN: of the receipt of packets and requests for lost packets.
                //EN: When we send acknowledge we set the next expected packet number
                //EN: When we send request for lost packet we set concrete packet number of lost packet
                System.Threading.Monitor.Enter(connectionRecord.LockerReceive);

                //EN: if cancellation requested - stop and release resources
                connectionRecord.CToken.ThrowIfCancellationRequested();

                if (connectionRecord.IsDone != 0)
                {
                    return;
                }

                if (!header.Flags.HasFlag(ReliableUdpHeaderFlags.RequestForPacket))
                {
                    //EN: drop packet
                    return;
                }

                //RU: расчет конечной границы окна, чтобы избежать ошибок с записью/чтением в несуществующий индекс
                //RU: в расчете берется граница окна + 1 - для получения подтверждений
                //EN: calculation of the final border of the window.
                int windowHighestBound = Math.Min((connectionRecord.WindowLowerBound + connectionRecord.WindowSize),
                                                  (connectionRecord.NumberOfPackets));

                //RU: проверка на попадание в окно
                //EN: check to get into the reception window
                if (header.PacketNumber < connectionRecord.WindowLowerBound || header.PacketNumber > windowHighestBound)
                {
                    //EN: drop packet
                    return;
                }

                connectionRecord.WaitForPacketsTimer.Change(connectionRecord.ShortTimerPeriod, -1);
                if (connectionRecord.CloseWaitTimer != null)
                {
                    connectionRecord.CloseWaitTimer.Change(-1, -1);
                }

                //RU: проверить на последний пакет:
                //EN: check for last packet
                if (header.PacketNumber == connectionRecord.NumberOfPackets)
                {
                    //RU: передача завершена
                    //EN: transfer completed
                    Debug.WriteLine("Done {0}! ", connectionRecord.TransmissionId);
                    Interlocked.Increment(ref connectionRecord.IsDone);
                    SetAsCompleted(connectionRecord);
                    return;
                }

                //RU: это ответ на первый пакет c подтверждением
                //EN: check for acknowledge of the first packet
                if ((header.Flags.HasFlag(ReliableUdpHeaderFlags.FirstPacket) && header.PacketNumber == 1))
                {
                    //RU: без сдвига окна
                    //EN: don't move window lower bound
                    SendPacket(connectionRecord);
                }
                //RU: пришло подтверждение о получении блока данных
                //EN: check confirmation of delivery of block of packets
                else if (header.PacketNumber == windowHighestBound)
                {
                    //Debug.WriteLine( "#{0} ask received", Header.PacketNumber );
                    //RU: сдвигаем окно
                    //EN: move window
                    connectionRecord.WindowLowerBound += connectionRecord.WindowSize;
                    //RU: обнуляем массив контроля передачи
                    //EN: nullify window control array
                    connectionRecord.WindowControlArray.Nullify();
                    SendPacket(connectionRecord);
                }
                //RU: это запрос на повторную передачу
                //EN: if we are here than it is request for retransmission
                else
                {
                    ReliableUdpStateTools.SendPacket(connectionRecord,
                                                     ReliableUdpStateTools.RetransmissionCreateUdpPayload(connectionRecord,
                                                                                                          header.PacketNumber));
                }
            }
            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);
            }
        }