REGISTER
请求。请求中包含设备的相关信息,如设备 ID、用户名、密码、设备类型等,这些信息用于 SIP 服务器对设备进行认证和识别。例如,设备的 REGISTER
请求消息头可能如下:REGISTER sip:server_ip:port SIP/2.0
From: <sip:device_id@domain>;tag=xxxx
To: <sip:device_id@domain>
Call-ID: xxxxxxxx
CSeq: 1 REGISTER
Max-Forwards: 70
User-Agent: device_agent_info
Expires: xxx // 注册有效期
其中,From
字段中的 device_id
是设备的唯一标识,domain
是设备所属的域;Expires
字段表示注册的有效期。
服务器认证:
401 Unauthorized
响应,要求设备在后续的注册请求中包含认证信息。401 Unauthorized
响应后,根据服务器要求的认证方式,重新生成包含认证信息的 REGISTER
请求并发送给服务器。例如,在 Authorization
字段中添加认证信息:REGISTER sip:server_ip:port SIP/2.0
From: <sip:device_id@domain>;tag=xxxx
To: <sip:device_id@domain>
Call-ID: xxxxxxxx
CSeq: 2 REGISTER
Max-Forwards: 70
User-Agent: device_agent_info
Expires: xxx
Authorization: Digest username="device_username", realm="server_realm", nonce="nonce_value", uri="sip:server_ip:port", response="response_value"
200 OK
响应,表示注册成功。设备注册成功后,SIP 服务器认为该设备为在线状态,设备也认为 SIP 服务器为在线状态。同时,服务器会在响应中告知设备下次刷新注册的时间。例如:SIP/2.0 200 OK
From: <sip:device_id@domain>;tag=xxxx
To: <sip:device_id@domain>
Call-ID: xxxxxxxx
CSeq: 2 REGISTER
Contact: <sip:device_id@device_ip:port>;expires=next_expires_time
其中,Contact
字段中的 expires
表示下次刷新注册的时间。
403 Forbidden
、500 Internal Server Error
等错误响应。设备应间隔一定时间(一般情况下不应短于 60s)后继续发起注册过程。REGISTER
请求,将 Expires
字段的值设置为 0,表示立即注销。例如:REGISTER sip:server_ip:port SIP/2.0
From: <sip:device_id@domain>;tag=xxxx
To: <sip:device_id@domain>
Call-ID: xxxxxxxx
CSeq: 3 REGISTER
Max-Forwards: 70
User-Agent: device_agent_info
Expires: 0
200 OK
响应,表示注销成功。设备注销后,SIP 服务器认为该设备为离线状态。REGISTER
、401 Unauthorized
、200 OK
等消息。这些消息的格式和字段含义遵循 SIP 协议的规范1。MessageDigest
类进行 MD5 等算法的计算。Socket
类或相关的网络库来实现 TCP 或 UDP 连接,与 SIP 服务器进行通信。SharedPreferences
、数据库等方式进行数据的存储和管理。本文以大牛直播SDK的Android平台GB28181设备接入模块为例,功能设计如下:
代码实现如下:
/*
* CameraPublishActivity.java
* initGB28181Agent 初始化参数
* Author: daniusdk.com
* WeChat: xinsheng120
*/
private boolean initGB28181Agent() {
if ( gb28181_agent_ != null )
return true;
getLocation(context_);
String local_ip_addr = IPAddrUtils.getIpAddress(context_);
Log.i(TAG, "initGB28181Agent local ip addr: " + local_ip_addr);
if ( local_ip_addr == null || local_ip_addr.isEmpty() ) {
Log.e(TAG, "initGB28181Agent local ip is empty");
return false;
}
gb28181_agent_ = GBSIPAgentFactory.getInstance().create();
if ( gb28181_agent_ == null ) {
Log.e(TAG, "initGB28181Agent create agent failed");
return false;
}
gb28181_agent_.addListener(this);
// 必填信息
gb28181_agent_.setLocalAddress(local_ip_addr);
gb28181_agent_.setServerParameter(gb28181_sip_server_addr_, gb28181_sip_server_port_, gb28181_sip_server_id_, gb28181_sip_domain_);
gb28181_agent_.setUserInfo(gb28181_sip_username_, gb28181_sip_password_);
// 可选参数
gb28181_agent_.setUserAgent(gb28181_sip_user_agent_filed_);
gb28181_agent_.setTransportProtocol(gb28181_sip_trans_protocol_==0?"UDP":"TCP");
// GB28181配置
gb28181_agent_.config(gb28181_reg_expired_, gb28181_heartbeat_interval_, gb28181_heartbeat_count_);
//com.gb.ntsignalling.Device gb_device = new com.gb.ntsignalling.Device("34020000001380000001", "安卓测试设备", Build.MANUFACTURER, Build.MODEL,
// "宇宙","火星1","火星", true);
com.gb.ntsignalling.Device gb_device = new com.gb.ntsignalling.Device("33010752991327811433", "安卓测试设备", Build.MANUFACTURER, Build.MODEL,
"宇宙","火星1","火星", true);
if (mLongitude != null && mLatitude != null) {
com.gb.ntsignalling.DevicePosition device_pos = new com.gb.ntsignalling.DevicePosition();
device_pos.setTime(mLocationTime);
device_pos.setLongitude(mLongitude);
device_pos.setLatitude(mLatitude);
gb_device.setPosition(device_pos);
gb_device.setSupportMobilePosition(true); // 设置支持移动位置上报
}
gb28181_agent_.addDevice(gb_device);
if (!gb28181_agent_.createSipStack()) {
gb28181_agent_ = null;
Log.e(TAG, "initGB28181Agent gb28181_agent_.createSipStack failed.");
return false;
}
boolean is_bind_local_port_ok = false;
// 最多尝试5000个端口
int try_end_port = gb28181_sip_local_port_base_ + 5000;
try_end_port = try_end_port > 65536 ?65536: try_end_port;
for (int i = gb28181_sip_local_port_base_; i < try_end_port; ++i) {
if (gb28181_agent_.bindLocalPort(i)) {
is_bind_local_port_ok = true;
break;
}
}
if (!is_bind_local_port_ok) {
gb28181_agent_.releaseSipStack();
gb28181_agent_ = null;
Log.e(TAG, "initGB28181Agent gb28181_agent_.bindLocalPort failed.");
return false;
}
if (!gb28181_agent_.initialize()) {
gb28181_agent_.unBindLocalPort();
gb28181_agent_.releaseSipStack();
gb28181_agent_ = null;
Log.e(TAG, "initGB28181Agent gb28181_agent_.initialize failed.");
return false;
}
return true;
}
initGB28181Agent() 完成基础化参数配置后,就开始发Register;
和注册相关的状态反馈如下:
@Override
public void ntsRegisterOK(String dateString) {
Log.i(TAG, "ntsRegisterOK Date: " + (dateString!= null? dateString : ""));
}
@Override
public void ntsRegisterTimeout() {
Log.e(TAG, "ntsRegisterTimeout");
}
@Override
public void ntsRegisterTransportError(String errorInfo) {
Log.e(TAG, "ntsRegisterTransportError error:" + (errorInfo != null?errorInfo :""));
}
注销的话,Expires字段的值为0即可。
在Android 平台上支持GB28181时,设备注册失败可能是由于设备信息配置问题、网络连接问题、服务器配置问题、协议兼容性问题或其他问题导致的。通过仔细检查和排除这些可能的原因,可以提高设备注册的成功率。感兴趣的开发者可以单独跟我沟通探讨。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。