Sipdroid實現SIP(六): SIP中的請求超時和重傳

目錄

一. Sipdroid的請求超時和重傳html

二. SIP中超時和重傳的定義java

三. 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, 主叫就取消了呼叫.this

1.2 初步推測

  • 被叫回復的100 Trying和180 Ringing都沒有收到? 
  • 服務器轉發的被叫回復的100 Trying和180 Ringing都沒有收到? 
  • 主叫的代碼裏是否有修改響鈴時間的參數? 
  • 主叫本地有什麼超時CANCEL的機制被魔法般地啓動了?

1.3 解決方法

從主叫對象ua開始追蹤基類: UA->InviteDialog->InviteTransactionClient, 發如今發送各種請求msg前有一個線程類InnerTimer對象的啓動, 這個線程的休眠時間, 就是響鈴時間.spa

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發送前,  初始化類對象, 它們通常會被命名爲transactioncode

 

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協議]學習初學筆記

相關文章
相關標籤/搜索