zoukankan      html  css  js  c++  java
  • Sipdroid实现SIP(六): SIP中的请求超时和重传

    目录

    一. Sipdroid的请求超时和重传

    二. SIP中超时和重传的定义

    三. RFC中超时和重传的定义


    一. Sipdroid的请求超时和重传

    Sipdroid实现SIP协议栈系列, 之前的文章仅涉及了SIP消息的基本概念, 比如:

    • 请求型消息: INVITE, REGISTER...
    • 应答型消息: 100 Trying, 180 Ringing, 200 OK, BYE, ACK...
    • 携带SDP信息
    • 携带认证信息

    这篇文章更深入一些, 介绍了SIP作为一种可靠传输, 涉及到的超时和重传机制. 也是在调试bug时发现的新大陆.

    1.1 出现的问题

    注册在同一个SIP Server的两个SIP Client互相呼叫时, 会话建立前的SIP信令一切正常, 双发也开始响铃, 但是被叫5s内不接听或拒接, 主叫就会发送CANCEL, 被叫就会回复100 Trying + 487 + 200 OK, 然后会话中断. 也就是响铃时间只有5s, 主叫就取消了呼叫.

    1.2 初步推测

    • 被叫回复的100 Trying和180 Ringing都没有收到? 
    • 服务器转发的被叫回复的100 Trying和180 Ringing都没有收到? 
    • 主叫的代码里是否有修改响铃时间的参数? 
    • 主叫本地有什么超时CANCEL的机制被魔法般地启动了?

    1.3 解决方法

    从主叫对象ua开始追踪基类: UA->InviteDialog->InviteTransactionClient, 发现在发送各类请求msg前有一个线程类InnerTimer对象的启动, 这个线程的休眠时间, 就是响铃时间.

    1.4 问题原因

    Sipdroid的请求超时参数设置错误. RFC推荐的32000被设置成5000, 导致INVITE请求在5s内没有收到200 OK回执, 就被视为超时, 主叫主动CANCEL了呼叫请求.  要修改的代码在SipStack类里, 该类描述了SIP协议栈的一些基本属性, 包括SIP默认使用端口, 默认传输协议, 默认超时时间等. 修改参数如下:

        /**
         * starting retransmission timeout (milliseconds); called T1 in RFC2361;
         * they suggest T1=500ms
         */
        public static long retransmission_timeout = 2000;
        
        /**
         * maximum retransmission timeout (milliseconds); called T2 in RFC2361; they
         * suggest T2=4sec
         */
        public static long max_retransmission_timeout = 16000;
        
        /** transaction timeout (milliseconds); RFC2361 suggests 64*T1=32000ms */
        //public static long transaction_timeout = 5000;[CHG]这里应该修改为RFC推荐值            
        public static long transaction_timeout = 32000;
        
        /** clearing timeout (milliseconds); T4 in RFC2361; they suggest T4=5sec */
        public static long clearing_timeout = 5000;

    一直知道TCP协议里有重传算法, 确保了传输可靠性, 而且是应用层基本无法质疑的可靠. 

    在有超时机制的msg发送前,  初始化类对象, 它们一般会被命名为transaction

    class InnerTimer extends Thread {
        long timeout;
        InnerTimerListener listener;
    
        public InnerTimer(long timeout, InnerTimerListener listener) {
            this.timeout = timeout;
            this.listener = listener;
            start();
        }
    
        public void run() {
            if (listener != null) {
                try {
                    Thread.sleep(timeout);
                    listener.onInnerTimeout();
                } catch (Exception e) {
    
                    e.printStackTrace();
                }
                listener = null;
            }
        }
    }
    class InnerTimerST extends java.util.TimerTask {
        static java.util.Timer single_timer = new java.util.Timer(true);
    
        // long timeout;
        InnerTimerListener listener;
    
        public InnerTimerST(long timeout, InnerTimerListener listener) { // this.timeout=timeout;
            this.listener = listener;
            single_timer.schedule(this, timeout);
        }
    
        public void run() {
            if (listener != null) {
                listener.onInnerTimeout();
                listener = null;
            }
        }
    }

    参考

    [1] [SIP协议]学习初学笔记

  • 相关阅读:
    122. Best Time to Buy and Sell Stock II
    121. Best Time to Buy and Sell Stock
    72. Edit Distance
    583. Delete Operation for Two Strings
    582. Kill Process
    indexDB基本用法
    浏览器的渲染原理
    js实现txt/excel文件下载
    git 常用命令
    nginx进入 配置目录时
  • 原文地址:https://www.cnblogs.com/elsarong/p/6246075.html
Copyright © 2011-2022 走看看