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协议]学习初学笔记

时间: 2024-10-24 20:46:55

Sipdroid实现SIP(六): SIP中的请求超时和重传的相关文章

angular学习笔记(二十六)-$http(4)-设置请求超时

本篇主要讲解$http(config)的config中的timeout项: $http({ timeout: number }) 数值,从发出请求开始计算,等待的毫秒数,超过这个数还没有响应,则返回错误 demo: html: <!DOCTYPE html> <html ng-app = 'HttpGet'> <head> <title>18.4 $http(2)</title> <meta charset="utf-8"

Android中客户端请求服务器端的方式讲解(一)附源码

Android中客户端请求服务器端的两种方式:Post方式和Get方式 在这里不直接赘述了,直接上源码如下: (1).Post的方式: /** * Post的请求方式 * * @param model * 请求序号 * @param paramList * 客户端请求的数据参数列表 * @return */ public JSONObject doPost(int model, List<NameValuePair> paramList) { try { // 客户端向服务器发送请求的数据 L

MVC之前的那点事儿系列(9):MVC如何在Pipeline中接管请求的?(转载)

MVC之前的那点事儿系列(9):MVC如何在Pipeline中接管请求的? 文章内容 上个章节我们讲到了,可以在HttpModules初始化之前动态添加Route的方式来自定义自己的HttpHandler,最终接管请求的,那MVC是这么实现的么?本章节我们就来分析一下相关的MVC源码来验证一下我们的这个问题. 先创建一个MVC3的Web Application,选择默认的模板以便创建以后就默认包含HomeController和AccountController.我们知道MVC要先接管请求才能通过

web过滤器中获取请求的参数(content-type:multipart/form-data)

1.前言: 1.1 在使用springMVC中,需要在过滤器中获取请求中的参数token,根据token判断请求是否合法: 1.2 通过requst.getParameter(key)方法获得参数值; 这种方法有缺陷:它只能获取  POST 提交方式中的Content-Type: application/x-www-form-urlencoded; HttpServletRequest request= (HttpServletRequest) req; String param = reque

python中http请求方法有哪些

在python开发(http://www.maiziedu.com/course/python-px/)中,我们一般通过get.post方式发送http请求,可是最近在使用python做接口测试,发现python中http请求方法有许多种,作者整理了一番,把python中http请求方法都总结了出来,分享给大家,具体内容如下所示:一.python自带库----urllib2python自带库urllib2使用的比较多,简单使用如下:import urllib2response = urllib2

php中Http请求方法和响应状态码整理教程

HTTP请求报文由请求行(request line).请求头部(header).空行和请求数据4个部分组成,格式如下 可见请求行由请求方法字段.URL字段和HTTP协议版本字段3个字段组成,它们用空格分 个HTTP请求报文由请求行(request line).请求头部(header).空行和请求数据4个部分组成,格式如下 可见请求行由请求方法字段.URL字段和HTTP协议版本字段3个字段组成,它们用空格分隔.HTTP请求方法: GET: 请求指定的页面信息,并返回实体主体. HEAD: 只请求页

struts中的请求数据自动封装

Struts 2框架会将表单的参数以同名的方式设置给对应Action的属性中.该工作主要是由Parameters拦截器做的.而该拦截器中已经自动的实现了String到基本数据类型之间的转换工作.在struts中,默认使用拦截器 <interceptor name="params" class="com.opensymphony.xwork2.interceptor.ParametersInterceptor"/> 进行请求数据自动封装,它会JSP中提交的

Android应用中网络请求库Volley的使用

接上文,这次来说一下如何使用Volley,会给出一些范例,和原理 Volley使用 StringRequest // 初始化一个请求队列,RequestQueue是volley库的类 RequestQueue queue = Volley.newRequestQueue(this); String url ="http://www.baidu.com"; //定义一个字符串型请求队列,需要传递4个参数分别是:url, 请求的方式(get, post..),响应成功的处理函数匿名对象,

jQuery 中 ajax 请求数据应用的一个小demo

举一个jquery中ajax的应用小 demo 便于以后的更多项目拓展 ,这里要注意的是保存的文件名和文件图片路径问题 ... ajax01.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title> ajax小例子 </title> </head> <body> <!--