国标GB28181协议客户端开发(二)程序架构和注册

本系列文章旨在探讨国标GB28181协议设备端的开发过程。本文将聚焦于架构设计和设备注册,并详细介绍了设备端的程序架构设计、exosip库介绍和接口分类,以及GB28181设备端的注册流程和信令交互报文。通过阅读本文,读者将深入了解GB28181协议设备端的架构设计原则、exosip库的使用方法,以及设备的注册过程和信令交互的关键报文。

一、程序架构设计

在GB28181协议设备端的开发中,良好的程序架构设计是保证系统稳定性和可扩展性的基础。我们可以考虑以下方面:

  1. 分层架构:将设备端的功能划分为不同的层次,如媒体层、控制层、存储层和网络层等,以实现模块化的开发和维护。

  2. 模块设计:根据功能需求,将设备端划分为不同的模块,如平台接入模块、媒体解析模块、编码模块、解码模块等。每个模块负责特定的功能,通过接口进行交互和通信。

  3. 数据结构设计:GB28181协议涉及到丰富的数据结构,如设备信息、媒体流、信令消息等。在设计数据结构时,需要考虑数据的组织和访问效率,以及与协议规范的兼容性。

以下为开发GB28181协议设备端的程序框架:

二、exosip库介绍和接口分类

eXosip是一个基于oSIP库的扩展库,用于实现SIP协议的开发。它提供了一个事件驱动的编程接口,用于处理SIP信令和实现SIP应用程序,广泛用于GB28181设备端的开发。它提供了丰富的接口和功能,可以简化开发过程。下面是eXosip的内部架构的概述:

  1. SIP上下文(SIP Context):

    eXosip库使用SIP上下文来管理和处理SIP会话。每个SIP上下文都有一个唯一的ID,可以通过函数eXosip_malloc()创建上下文。应用程序可以创建多个上下文来处理不同的SIP会话。

  2. 事件循环(Event Loop):

    eXosip库通过事件循环机制处理接收到的SIP消息和事件。事件循环会持续监听网络套接字,等待SIP消息的到达或定时器事件的触发。当有事件发生时,eXosip库将生成相应的事件,并将其放入事件队列中等待处理。

  3. 事件处理器(Event Handler):

    eXosip库提供了一组事件处理器函数,用于处理各种类型的事件,如注册、呼叫邀请、消息收发等。应用程序可以根据需要注册相应的事件处理器函数,并在事件发生时执行自定义的逻辑。

  4. SIP消息处理器(SIP Message Handler):

    eXosip库提供了一组函数来处理SIP消息,包括解析和构建SIP请求和响应。它使用oSIP库的底层功能来处理SIP消息的解析和组装,并提供了更高级别的接口供应用程序使用。

  5. 网络通信:

    eXosip库使用底层的网络套接字进行SIP通信。它提供了与网络层交互的功能,如创建和绑定套接字、发送和接收SIP消息等。应用程序可以根据需要配置和管理网络通信相关的参数。

eXosip库的内部架构充分利用了oSIP库提供的底层功能,并提供了更高级别的接口和事件驱动的编程模型,使开发者能够更方便地实现基于SIP的应用程序。

exosip库的接口可以分为以下几类:

  1. 初始化和配置接口:包括库的初始化、设置SIP协议栈的参数、配置监听端口等。

  2. 注册和注销接口:用于设备的注册和注销操作,包括注册请求的发送和接收处理等。

  3. 信令交互接口:用于发送和接收SIP信令消息,如呼叫邀请、媒体流控制等。

三、exosip初始化和消息循环

在使用exosip库前,需要进行初始化和配置的操作。具体步骤如下:

  1. 初始化exosip库:调用初始化接口,初始化exosip库,并设置一些全局参数。

  2. 配置SIP协议栈:通过配置接口,设置SIP协议栈的相关参数,如IP地址、端口等。

  3. 创建SIP上下文:使用上下文接口,创建一个SIP上下文,用于后续的注册和信令交互操作。

#include <osip2/osip.h>
#include <eXosip2/eXosip.h> // 初始化eXosip和osip栈
exosip_ = eXosip_malloc();
ret_code = eXosip_init(exosip_);
if (ret_code != OSIP_SUCCESS)
{
SIMPLE_LOG("Can't initialize eXosip!");
exit(1);
} // 配置exosip库参数,如IP地址和端口
ret_code = eXosip_listen_addr(exosip_, IPPROTO_UDP, NULL, cfg_.sip_local_port, AF_INET, 0);
if (ret_code != OSIP_SUCCESS)
{
SIMPLE_LOG("eXosip_listen_addr error!"); eXosip_quit(exosip_); exit(1);
} eXosip_set_user_agent(exosip_, "HbsGBSIP-1.0"); // 发送初始注册报文
SipSendRegister(false, nullptr); // 接收和处理SIP报文
while (!is_need_stop_)
{
// 处理事件
eXosip_event_t* sip_event = eXosip_event_wait(exosip_, 0, 10); // 一般处理401/407采用库默认处理
eXosip_lock(exosip_);
eXosip_default_action(exosip_, sip_event);
eXosip_unlock(exosip_); // 超时
if (sip_event == NULL)
{
continue;
} // 尝试解析报文头部信息
OSipMsgParser msg_parser;
if (sip_event->request)
{
msg_parser.ParseHeader(sip_event->request);
} switch (sip_event->type)
{
case EXOSIP_REGISTRATION_SUCCESS: {
// 注册成功处理
break;
}
case EXOSIP_REGISTRATION_FAILURE: {
// 注册失败处理
break;
}
case EXOSIP_MESSAGE_NEW: {
// 收到新的SIP消息处理
if (sip_event->request) {
// 处理请求消息
osip_message_t* request = sip_event->request;
// 解析和处理请求消息
} else if (sip_event->response) {
// 处理响应消息
osip_message_t* response = sip_event->response;
// 解析和处理响应消息
}
break;
}
case EXOSIP_CALL_INVITE: {
// 收到呼叫邀请处理
// 解析和处理呼叫邀请消息
break;
}
// 其他事件处理... default:
break;
} // 释放事件
eXosip_event_free(sip_event);
} // 清理exosip库资源
eXosip_quit(exosip_);
osip_free(exosip_);
exosip_ = NULL;

四、GB28181注册过程中的信令交互报文

注册流程描述如下:

  1. SIP代理向SIP服务器发送 Register请求;

  2. SIP服务器向 SIP代理发送响应401,并在响应的消息头 WWW_Authenticate字段中给出

    适合SIP代理的认证体制和参数;

  3. SIP代理重新向SIP服务器发送 Register请求,在请求的 Authorization字段给出信任书,

    包含认证信息;

  4. SIP 服务器对请求进行验证,如果检查出 SIP 代理身份合法,向 SIP 代理发送成功响应

    200OK,如果身份不合法则发送拒绝服务应答。

WireShark截包后可见:

  1. 第一次注册:
REGISTER sip:34020000002000000001@192.168.1.54:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK639602844
From: <sip:34020000001110000002@192.168.1.54:10561>;tag=91827836
To: <sip:34020000001110000002@192.168.1.54:10561>
Call-ID: 2847584547
CSeq: 1 REGISTER
Contact: <sip:34020000001110000002@192.168.1.54:10561;line=00c3a618be4c249>
Max-Forwards: 70
User-Agent: HbsGBSIP-1.0
Expires: 3600
Content-Length: 0
  1. GB28181平台返回401错误:
SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK639602844
From: <sip:34020000001110000002@192.168.1.54:10561>;tag=91827836
To: <sip:34020000001110000002@192.168.1.54:10561>;tag=1724123124
Call-ID: 2847584547
CSeq: 1 REGISTER
WWW-Authenticate: Digest realm="34020000", nonce="awer23sdfj123123", opaque="c3a02f1ecb122d255c4ae2266129d044", algorithm=MD5
User-Agent: General
Content-Length: 0
  1. 加上鉴权信息后第二次发送注册报文:
REGISTER sip:34020000002000000001@192.168.1.54:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK2311457380
From: <sip:34020000001110000002@192.168.1.54:10561>;tag=91827836
To: <sip:34020000001110000002@192.168.1.54:10561>
Call-ID: 2847584547
CSeq: 0 REGISTER
Contact: <sip:34020000001110000002@192.168.1.54:10561;line=00c3a618be4c249>
Authorization: Digest username="34020000001110000002", realm="34020000", nonce="awer23sdfj123123", uri="sip:34020000002000000001@192.168.1.54:5060", response="dc953f5c48a92517ff6542ef6cd97e20", algorithm=MD5, opaque="c3a02f1ecb122d255c4ae2266129d044"
Max-Forwards: 70
User-Agent: HbsGBSIP-1.0
Expires: 3600
Content-Length: 0
  1. GB28181平台返回200注册成功:
SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.168.1.54:10561;rport;branch=z9hG4bK2311457380
From: <sip:34020000001110000002@192.168.1.54:10561>;tag=91827836
To: <sip:34020000001110000002@192.168.1.54:10561>;tag=31243r3412
Call-ID: 2847584547
CSeq: 0 REGISTER
User-Agent: General
Date: 2023-03-15T16:18:33
Expires: 300
Content-Length: 0

调用eXosip进行注册的代码如下:

osip_message_t* reg = nullptr;

SIMPLE_LOG("new build register\n");

std::string from_str = MakeSIPFromToStr(cfg_.sip_local_device_id,
cfg_.sip_local_ip, cfg_.sip_local_port);
std::string to_str = MakeSIPFromToStr(cfg_.sip_server_id,
cfg_.sip_server_ip, cfg_.sip_server_port); register_id_ = eXosip_register_build_initial_register(exosip_,
from_str.c_str(), //"sip:34010000002000000001@127.0.0.1:7777",
to_str.c_str(), //"sip:34020000002000000001@127.0.0.1:5060",
NULL, expire_val, &reg); auto ret = eXosip_register_send_register(exosip_, register_id_, reg);

合作请加WX:hbstream或企鹅:229375788。(转载请注明作者和出处)

合作请加作者hbstream(http://haibindev.cnblogs.com),转载请注明作者和出处

国标GB28181协议客户端开发(二)程序架构和注册的更多相关文章

  1. 基于GBT28181:SIP协议组件开发-----------第四篇SIP注册流程eXosip2实现(一)

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3945294.html. 上章节讲解了利用自主开发的组件SIP组件l ...

  2. 基于GBT28181:SIP协议组件开发-----------第三篇SIP注册流程分析实现

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3941172.html,qq:1269122125. 上两章节简要的 ...

  3. webpack+react多页面开发(二)-终极架构

    webpack4+react16多页面架构 webpack在单页面打包上应用广泛,以create-react-app为首的脚手架众多,单页面打包通常指的是将业务js,css打包到同一个html文件中, ...

  4. 基于GBT28181:SIP协议组件开发-----------第五篇SIP注册流程eXosip2实现(二)

    原创文章,引用请保证原文完整性,尊重作者劳动,原文地址http://www.cnblogs.com/qq1269122125/p/3966794.html. 上章节讲解了讲解一个用eXosip2库实现 ...

  5. 接口自动化测试:Thrift框架RPC协议客户端开发

    import java.lang.Thread.State;import java.util.Iterator;import java.util.List; import org.apache.thr ...

  6. EasyNVR和EasyDSS云平台联手都不能解决的事情,只有国标GB28181能解决了

    需求痛点 我们经常收到这样一种需求,就是将客户手里的各种类型的网络摄像机IPC和网络硬盘录像机NVR进行统一的整合接入和管理,并进行常规的直播.存储.录像检索和回放等操作,而这个时候我们通常会选择用E ...

  7. 【HELLO WAKA】WAKA iOS客户端 之二 架构设计与实现篇

    上一篇主要做了MAKA APP的需求分析,功能结构分解,架构分析,API分析,API数据结构分析. 这篇主要讲如何从零做iOS应用架构. 全系列 [HELLO WAKA]WAKA iOS客户端 之一 ...

  8. Azure-如何排查应用程序网关返回 HTTP Code 502 或客户端得到应用程序网关响应慢的问题(二)

    问题描述 经过如何排查应用程序网关返回 HTTP Code 502 或客户端得到应用程序网关响应慢的问题(一)中的排查步骤,可以判断出是由于 Web 服务器自身问题导致的响应异常. 那么可以在 IIS ...

  9. Atitit.使用引擎加脚本架构的设计 使用php,js来开发桌面程序。。

    Atitit.使用引擎加脚本架构的设计 使用php,js来开发桌面程序.. 1. 引擎加脚本架构 跨平台,桌面与web的优势1 2. 架构桌面引擎(java,c#)2 3. php桌面引擎要点2 3. ...

  10. iOS开发人员程序许可协议

    请细致阅读以下的许可协议条款和条件之前下载或使用苹果软件.   这些条款和条件构成你和苹果之间的法律协议.   iOS开发人员程序许可协议   目的 你想使用苹果软件(例如以下定义)来开发一个或多个应 ...

随机推荐

  1. 免费注册 Redhat 开发者并且进行订阅和激活

    注册 一.进入 https://www.redhat.com/wapps/ugc/register.html 进行注册 二.然后通过这个网址进入开发者平台 https://developers.red ...

  2. 【CTF】系统调用号查询表

    32位 #ifndef _ASM_X86_UNISTD_32_H #define _ASM_X86_UNISTD_32_H 1 #define __NR_restart_syscall 0 #defi ...

  3. python实现远程桌面

    项目旨在让大家理解远控软件的原理,通过远控桌面可以实现远程控制我们的电脑,更好更方便的管理电脑.文末将给出初始版的完整代码,需要使用到的其他工具也会有所说明.最终实现的效果就是只要用户点击了客户端的程 ...

  4. 四月十二号java基础知识

    1.面向对象的编程思想是力图使在计算机语言中对事物的描述与现实世界中该事物的本来面目尽可能地一致.2.类(class)和对象(object)是面向对象程序设计方法中最核心的概念3.类是对某一事物的描述 ...

  5. 帝国ECMS静态生成为一行代码/静态页面打乱教程

    一.内容页变成一行修改1.打开文件e/class/functions.php2.找到以下函数 function GetHtml($classid,$id,$add,$ecms=0,$doall=0) ...

  6. win11 计算器的进制转换

  7. SpringBoot开启日志级别

    #开启logging logging.level.org.springframework.boot.autoconfigure: error logging: level: main.blog.map ...

  8. vue本地开发配置及项目部署

    一,  二,本地模拟配置代理,请求qq音乐的接口数据  三,axios请求头封装               参考http://www.axios-js.com/zh-cn/docs/#%E4%BB% ...

  9. Lucas定理——定义、证明、实现、运用

    目录 什么是Lucas定理 证明Lucas定理 Lucas定理求解组合数的C++实现 什么是Lucas定理 这是一个有助于分解组合数来求解的定理,适合模数小,数字大的问题. 有质数 \(p\),对于\ ...

  10. Go坑:time.After可能导致的内存泄露问题分析

    Go 中 time.After 可能导致的内存泄露 一.Time 包中定时器函数 go v1.20.4 定时函数:NewTicker,NewTimer 和 time.After 介绍 time 包中有 ...