
协议即约定,通信协议约定了通信双方交互所遵循的方式和细则。TR069协议约定用户侧设备(Customer Premises Equipment,即CPE)和自动配置服务器(Auto-Configuration Server,即ACS)之间交互的规则。我们知道HTTP协议是基于TCP协议,COAP协议是基于UDP协议,而这里的TR069协议则是基于HTTP1.1的协议传输,SOAP标准封装XML的消息内容格式,消息内容部分如下图1:

TR069协议提供了对下一代网络中家庭网络设备进行管理配置的通用框架、消息规范、管理方法和数据模型。在网管模型中,ACS负责对终端设备CPE进行远程集中管理,解决CPE设备的管理困难,节约维护成本,提高问题解决效率。

ACS实现对CPE的远程管理,核心便是ACS与CPE之间的连接交互。不同于MQTT协议,客户端与服务器之间维持一个长链接,ACS同CPE的连接仅在存在交互需要时建立短链接。
CPE首次启动会主动对ACS发起HTTP连接,进行注册上线动作,通过RPC方法中的inform方法上报0 BOOTSTRAP和1 BOOT(如上图SOAP封装的XML消息内容案例),如平台有需要配置或者获取的参数,也会在这次连接中进行。交互如下:

第一步:CPE直接对ACS发起HTTP连接请求,请求案例头部如下:
POST /ACS-server/test HTTP/1.1
SOAPAction:
Content-Length: 3923
......第二步:ACS响应401,要求CPE进行HTTP Digest Authentication认证,即摘要认证,响应案例如下:
HTTP/1.1 401 Unauthorized
Server: XXX
WWW-Authenticate: Digest
realm="XXX",qop="XXX",nnotallow="5ad62dabf90594eed8d2d72cec12e5f9",opaque="60D0FDDCC498497B82138713D1383D9F"
......第三步:CPE根据ACS响应的WWW-Authenticate信息,以及url、username和password,按照摘要认证算法计算response,构建出再次请求的摘要认证信息Authorization,并再次发起HTTP请求,进行inform上报。携带认证信息再次请求,案例如下:
POST /ACS-server/test HTTP/1.1
SOAPAction:
Authorization: Digest realm="XXX", username="XXX", algorithm="MD5", nnotallow="5ad62dabf90594eed8d2d72cec12e5f9", uri="/ACS-server/test", nc=00000001, cnnotallow="12327701", respnotallow="XXXXXX", opaque="60D0FDDCC498497B82138713D1383D9F", qop="XXX"
Content-Length: 3923
......第四步:ACS响应200 OK,SOAP内容为InformResponse,摘要认证到这里已经完成。根据响应头的Set-Cookie信息设置CPE下个请求的Cookie。案例如下:
HTTP/1.1 200 OK
Server: XXX
Set-Cookie:
JSESSIONID=15F51C74ED3AE0FE45A382BEBC145D29; Path=XXX;XXX
......第五步:CPE发起的一个空的HTTP请求,根据TR069协议,消息体长度必须为0,如下案例可以看到Content-Length是0:
POST /ACS-server/test HTTP/1.1
Authorization: Digest realm="XXX", username="XXX", algorithm="MD5", nnotallow="5ad62dabf90594eed8d2d72cec12e5f9", uri="/ACS-server/test", nc=00000002, cnnotallow="12327701", respnotallow="XXXXXX", opaque="60D0FDDCC498497B82138713D1383D9F", qop="XXX"
Content-Length: 0
Cookie:
JSESSIONID=15F51C74ED3AE0FE45A382BEBC145D29
......第六步:ACS响应HTTP 空请求,封装SOAP调用RPC方法,对终端设备进行参数配置或者查询等操作。
HTTP/1.1 200 OK
Server: XXX
Content-Type: text/xml;charset=UTF-8
Content-Length: 2226
......第七步:CPE发起请求,封装SOAP对应响应RPC方法。如果终端管理平台查询后还需要进行配置,则第六步和第七步会有两次,如都不需要,则第六步和第七步可省略。如存在,案例如下:
POST /ACS-server/acs HTTP/1.1
SOAPAction:
Authorization: Digest realm="XXX", username="XXX", algorithm="MD5", nnotallow="5ad62dabf90594eed8d2d72cec12e5f9", uri="/ACS-server/test", nc=00000003, cnnotallow="12327701", respnotallow="XXXXXX", opaque="60D0FDDCC498497B82138713D1383D9F", qop="XXX"
Content-Length: 528
Cookie:
JSESSIONID=15F51C74ED3AE0FE45A382BEBC145D29
......第八步:ACS下发一个空HTTP响应,根据TR069协议,状态码使用“204(无内容)”,表示本次会话结束。案例如下:
HTTP/1.1 204 No Content
Server: XXX
Date: Fri, 23 Jan 2023 00:15:14 GMT这里我们针对第三步的摘要认证展开说明。这里简要说明下WWW-Authenticate和Authorization中涉及到的一些参数,更多详细内容可以自行参阅RFC2617等相关文档。
➤ digest ==>认证方式
➤ realm ==>领域,领域参数是强制的,必须存在
➤ qop ==>保护的质量,“auth”表示只进行身份查验, “auth-int”表示进行查验外,还有一些完整性保护
➤ nonce ==>服务器侧生成的随机数,在每个401回应产生时,被唯一创建,为防止攻击产生,参与加密
➤ cnonce ==>即client nonce
➤ uri ==>客户端想要访问的URL
➤ nc ==>连续请求次数,在同一个TCP连接里,设备每POST一次,nc+1
➤ algorithm ==>用来生产摘要及校验和的算法对
➤ response ==>用来证明用户是否知道口令
response计算通常过程分以下三步[2]:
第一步:计算HA1
第二步:计算HA2
第三步:根据HA1和HA2计算response
Authorization构建:CPE端生成cnonce,nc从00000000开始累计,response根据上述公式计算,opaque、qop、nonce、realm继承自WWW-Authenticate,添加上username、algorithm和uri。
此外,终端管理系统可能还会对Manufacturer、OUI等参数进行查验,如查验不通过,响应403,即服务器理解客户的请求,但拒绝处理它。
通过ACS对CPE进行参数配置时,ACS作为主动方触发本次连接。此时,ACS主动连接CEP,方式有两种:
(1)非NAT模式下,ACS对CPE发起HTTP连接请求,使用终端上报的地址:Device.ManagementServer.ConnectionRequestURL,终端要求进行HTTP摘要认证。
(2)NAT模式下,ACS在公网环境下与内网下CPE交互,通过NAT穿越获取CPE公网地址进行交互,实现流程见下文。
NAT,即网络地址转换。STUN 存在的目的就是进行NAT穿越[1],这里STUN将作为一个工具来服务于本次的ACS连接CPE实现。让终端用来发现其在公网IP和端口,并作为一种保活(keep-alive)协议来维持NAT的绑定。
NAT模式下,ACS连接CPE实现具体如下:
第一步:基于STUN协议实现ACS与CPE之间的捆绑请求和响应,并维持。可借助第三方开源JSTUN库,地址:https://gitee.com/javabedlamite/JSTUN/。如下是相关报文案例:

第二步:根据捆绑响应解析CPE公网IP和端口。根据STUN协议定义,MAPPED-ADDRESS属性对应即是客户端映射地址;在这里也是CPE的公网地址。

第三步:根据映射的端口地址构建终端管理系统的UDP回连地址;并上报ACS。涉及使用TR069数据模型中以下两个参数:
通知上报ACS,CPE支持NAT穿越,以及其在公网UDP回连地址。
第四步:某时刻,ACS需要对CPE进行配置,只需终端管理平台对CPE的发起UDP请求,终端设备侧解析后,触发CPE对ACS发起Inform 6 CONNECTION REQUEST(根据Tr069协议,Inform 6表明本次会话是由ACS侧要求而建立的)。到此ACS连接CPE完成。
第五步:在本次连接中,ACS下发对CPE的配置、查询、重启、诊断等约定支持的任务,CPE执行并响应。
整体流程大致实现可如下:

ACS和CPE之间双向连接建立的实现,是终端管理系统远程管理终端的基本和前提。本文主要就ACS连接CEP和CPE连接ASC,各详细讲述一种连接实现方式和流程。目前,家庭智能网关普遍通过TR069协议纳管于各省份的省侧管理平台,一些机顶盒也在通过TR069协议进行纳管;在万物互联背景下,未来规模也许会更大。
我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden
华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.
MIMO技术的优缺点优点通过下面三个增益来总体概括:阵列增益。阵列增益是指由于接收机通过对接收信号的相干合并而活得的平均SNR的提高。在发射机不知道信道信息的情况下,MIMO系统可以获得的阵列增益与接收天线数成正比复用增益。在采用空间复用方案的MIMO系统中,可以获得复用增益,即信道容量成倍增加。信道容量的增加与min(Nt,Nr)成正比分集增益。在采用空间分集方案的MIMO系统中,可以获得分集增益,即可靠性性能的改善。分集增益用独立衰落支路数来描述,即分集指数。在使用了空时编码的MIMO系统中,由于接收天线或发射天线之间的间距较远,可认为它们各自的大尺度衰落是相互独立的,因此分布式MIMO
遍历文件夹我们通常是使用递归进行操作,这种方式比较简单,也比较容易理解。本文为大家介绍另一种不使用递归的方式,由于没有使用递归,只用到了循环和集合,所以效率更高一些!一、使用递归遍历文件夹整体思路1、使用File封装初始目录,2、打印这个目录3、获取这个目录下所有的子文件和子目录的数组。4、遍历这个数组,取出每个File对象4-1、如果File是否是一个文件,打印4-2、否则就是一个目录,递归调用代码实现publicclassSearchFile{publicstaticvoidmain(String[]args){//初始目录Filedir=newFile("d:/Dev");Datebeg
通常,数组被实现为内存块,集合被实现为HashMap,有序集合被实现为跳跃列表。在Ruby中也是如此吗?我正在尝试从性能和内存占用方面评估Ruby中不同容器的使用情况 最佳答案 数组是Ruby核心库的一部分。每个Ruby实现都有自己的数组实现。Ruby语言规范只规定了Ruby数组的行为,并没有规定任何特定的实现策略。它甚至没有指定任何会强制或至少建议特定实现策略的性能约束。然而,大多数Rubyist对数组的性能特征有一些期望,这会迫使不符合它们的实现变得默默无闻,因为实际上没有人会使用它:插入、前置或追加以及删除元素的最坏情况步骤复
在ruby中,你可以这样做:classThingpublicdeff1puts"f1"endprivatedeff2puts"f2"endpublicdeff3puts"f3"endprivatedeff4puts"f4"endend现在f1和f3是公共(public)的,f2和f4是私有(private)的。内部发生了什么,允许您调用一个类方法,然后更改方法定义?我怎样才能实现相同的功能(表面上是创建我自己的java之类的注释)例如...classThingfundeff1puts"hey"endnotfundeff2puts"hey"endendfun和notfun将更改以下函数定
我目前有一个reddit克隆类型的网站。我正在尝试根据我的用户之前喜欢的帖子推荐帖子。看起来K最近邻或k均值是执行此操作的最佳方法。我似乎无法理解如何实际实现它。我看过一些数学公式(例如k表示维基百科页面),但它们对我来说并没有真正意义。有人可以推荐一些伪代码,或者可以查看的地方,以便我更好地了解如何执行此操作吗? 最佳答案 K最近邻(又名KNN)是一种分类算法。基本上,您采用包含N个项目的训练组并对它们进行分类。如何对它们进行分类完全取决于您的数据,以及您认为该数据的重要分类特征是什么。在您的示例中,这可能是帖子类别、谁发布了该项
我查看了Stripedocumentationonerrors,但我仍然无法正确处理/重定向这些错误。基本上无论发生什么,我都希望他们返回到edit操作(通过edit_profile_path)并向他们显示一条消息(无论成功与否)。我在edit操作上有一个表单,它可以POST到update操作。使用有效的信用卡可以正常工作(费用在Stripe仪表板中)。我正在使用Stripe.js。classExtrasController5000,#amountincents:currency=>"usd",:card=>token,:description=>current_user.email)
虽然1.8.7的构建我似乎有一个向后移植的Shellwords::shellescape版本,但我知道该方法是1.9的一个特性,在1.8的早期版本中绝对不支持.有谁知道我在哪里可以找到(以Gem形式或仅作为片段)针对Ruby转义的Bourne-shell命令的强大独立实现? 最佳答案 您也可以从shellwords.rb中复制您想要的内容。在Ruby的颠覆存储库的主干中(即GPLv2'd):defshellescape(str)#Anemptyargumentwillbeskipped,soreturnemptyquotes.ret