精华内容
下载资源
问答
  • 1.举例解释更容易理解 2.。。。。。。。。。。。。。。。。。。。。。。。。。。
  • [color=#FF6600][return: XmlElement("return", Form = XmlSchemaForm.Unqualified)][/color] public string MakeFile(string filename,string filesize) ...服务端怎么返回客户端标记的返回格式。 谢谢
  • 服务端各种安全机制,比如身份验证,这一条的情况在于,有的前端做身份验证就是调用一下接口,获取到类似token字段,自己也不知道是什么意思,就乱丢乱用等。 本质上来说,前端是做不了什么安全措施的,但是,相应...

    客户端、前端、后端、服务端的区别分别是什么?

    客户端是指开发面向客户的程序,分很多平台,比如Windows 安卓 苹果,还有游戏客户端也算一类。

    前端指的是通过浏览器和用户交互的那部分。

    后端是在服务器上跑的,一般是管理数据,为前端、客户端提供数据传输的。

    服务器端就是后端。

    服务端各种安全机制,比如身份验证,这一条的情况在于,有的前端做身份验证就是调用一下接口,获取到类似token字段,自己也不知道是什么意思,就乱丢乱用等。

    本质上来说,前端是做不了什么安全措施的,但是,相应的拦截和安全还是要做,因为可以帮后端挡掉很多低质量攻击以及前端自身的用户体验。

    客户端是默认支持json的,后端是需要处理的。这点可以引申到,前后端各自传递的数据格式问题。有些前端 null undefined 空串分不清楚,到了后端就各种问题。

    展开全文
  • rtmp服务端实现

    2017-10-14 10:13:00
    先就最让人困惑(至少我是这样)且网上也很少找到答案的一个点讲一下id各是什么意思? (如果我哪里理解错了,希望大神指出,毕竟我也是看了好多资料及官方文档总结的) chunk stream id (cs id) 属于Chunk Basic ...

    前言

      网上好像没一篇讲的很完善的,可能和公司保密有关吧。先就最让人困惑(至少我是这样)且网上也很少找到答案的一个点讲一下id各是什么意思? (如果我哪里理解错了,希望大神指出,毕竟我也是看了好多资料及官方文档总结的)

    chunk stream id (cs id)     属于Chunk Basic Header                  占6bits
    message type id                属于Chunk Message Header           占1byte    
    message stream id           属于Chunk Message Header           占4bytes

    我们可以逆向推理:
    接收端(一个chunk stream链接)收到的都是chunk 那么会根据chunk stream id来组合成不同的message,相同的chunk stream id当然就属于同一message咯 但是会有不同的message,比如音频、视频、命令消息等,那么会根据message type id来区分是哪一类消息,比如我们通过message type id知道了是视频消息,这时可能存在一种可能,对方同时发送了视频a和视频b(虽然这种情况很少,而且按照官方文档的原话:this defeats the benefits of the header compression),那么就会根据message stream id来进一步区分了。

    下面部分是我综合了网上几个写的比较好的文章而来的,但是我没保留原文网址,如果原作者反对,我会立即删除。

    rtmp介绍

      RTMP 是Real-Time Messaging Protocol(实时消息传送协议)的缩写,它是Adobe Systems公司为Flash播放器和服务器之间音频、视频和数据传输开发的协议。这是一个标准的,未加密的实时消息传递协议,默认端口是1935。

    rtmp协议分析

      参考官方文档:rtmp_specification_1.0.pdf(不能完全相信该文档,adobe的这份文档公认的差)

      在RTMP协议中信令和媒体数据都称之为Message,在网络中传输这些Message,为了区分它们肯定是要加一个Message head的,所以RTMP协议也有一个Message head,还有一个问题因为RTMP协议是基于TCP的,由于TCP的包长度是有限制的(一般来说不超过1500个字节),而RTMP的Message长度是有可能很大的,像一个视频帧的包可能会有几十甚至几千K,这个问题就必然有一个分片的问题,在RTMP协议中对应的说法就是chunk,每一个Message + head都是由一个和多个chunk组成的。

      一个Message + head可以分成一个和多个chunk,为了区分这些chunk,肯定是需要一个chunk head的,具体的实现就把Message head的信息和chunk head的信息合并在一起以chunk head的形式表现。

      一个完整的chunk的组成如下图所示
    rtmp chunk

    Chunk basic header:
    该字段包含chunk的stream ID和 type 。chunk的Type决定了消息头的编码方式。该字段的长度完全依赖于stream ID,该字段是一个可变长的字段。
    Chunk Msg Header:0, 3 ,7, 11
    该字段包含了将要发送的消息的信息(或者是一部分,一个消息拆成多个chunk的情况下是一部分)该字段的长度由chunk basic header中的type决定。
    Extend Timestamp: 0 ,4 bytes
    该字段发送的时候必须是正常的时间戳设置成0xffffff时,当正常时间戳不为0xffffff时,该字段不发送。当时间戳比0xffffff小该字段不发送,当时间戳比0xffffff大时该字段必须发送,且正常时间戳设置成0xffffff。
    Chunk Data
    实际数据(Payload),可以是信令,也可以是媒体数据。

    Chunk basic header

      chunk basic head的长度为1~3个字节,具体长度主要是依赖chunk stream ID的长度,所谓chunk stream ID是flash server用来管理连接的客户端的信令交互的标识,在red5的文档中称之为channel ID,协议最大支持65597个streamID 从3~65599。ID 0,1,2为协议保留,0代表ID是64~319(第二个byte + 64);1代表chunk stream ID为64~65599((第三个byte)* 256 + 第二个byte + 64)(小端表示);2代表该消息为低层的协议(在RTMP协议中控制信令的chunk stream ID都是2)。3~63的chunk stream ID就是该byte的值。没有附加的字段来标识chunk stream streamID。在这里要指出的是虽然RTMP的chunk stream ID理论是可以达到65599,但是目前使用的chunk stream ID很少,2~7都是约定的,8是用来传输publish play等命令,其他的chunk stream ID目前好像没有使用,至少我不知道用来干嘛的。
    所以目前chunk basic head的长度一般为1个字节。这一个字节由两部分组成

                               +++++++++++++++++++
                               +fmt    +  cs id              +
                               +++++++++++++++++++

    fmt占两个bit用来标识紧跟其后的chunk Msg Header的长度,cs id占六个bit。
    两位的fmt取值为 0~3,分别代表的意义如下:
    case 0:chunk Msg Header长度为11;
    case 1:chunk Msg Header长度为7;
    case 2:chunk Msg Header长度为3;
    case 3:chunk Msg Header长度为0;
    所以 只有一个字节的chunk basic header取值为 chunk basic header = (fmt << 6) | (cs id).

    Chunk Msg Header

      Chunk Msg Header的长度是可变的,Chunk Msg Header可变的原因是为了压缩传输的字节数,把一些相同类型的chunk的head去掉一些字节,换句话说就是四种类型的包头都可以通过一定的规则还原成11个字节,这个压缩和还原在RTMP协议中称之为复用/解复用。
      那我们以11个字节的完整包头来解释Chunk Msg Header,如图所示

    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    +++++timestamp+message length+ message type id +message stream id+++++
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

    Timestamp:3bytes
    对于type 0的chunk,绝对时间戳在这里表示,如果时间戳值大于等于0xffffff(16777215),该值必须是0xffffff,且时间戳扩展字段必须发送,其他情况没有要求。
    message length:3bytes
    Message 的长度,注意这里的长度并不是跟随chunk head其后的chunk data(Payload)的长度,而是前文提到的一条信令或者一帧视频数据或音频数据的长度。前文提到过信令或者媒体数据都称之为Message,一条 Message可以分为一条或者多条chunk。
    message type id:1byte

    Message的类型ID

    0×01    Chunk Size  changes the chunk size for packets 
    0×02    Unknown     
    0×03    Bytes Read  send every x bytes read by both sides 
    0×04    Ping    ping is a stream control message, has subtypes 
    0×05    Server BW   the servers downstream bw 
    0×06    Client BW   the clients upstream bw 
    0×07    Unknown     
    0×08    Audio Data  packet containing audio 
    0×09    Video Data  packet containing video data 
    0x0A-0x0E   Unknown       
    0x0F    FLEX_STREAM_SEND    TYPE_FLEX_STREAM_SEND 
    0x10    FLEX_SHARED_OBJECT  TYPE_FLEX_SHARED_OBJECT 
    0x11    FLEX_MESSAGE    TYPE_FLEX_MESSAGE  
    0×12    Notify  an invoke which does not expect a reply 
    0×13    Shared Object   has subtypes 
    0×14    Invoke  like remoting call, used for stream actions too. 
    0×16    StreamData  这是FMS3出来后新增的数据类型,这种类型数据中包含AudioData和VideoData

    message stream id:4bytes
    message stream id的字节序是小端序,这个字段是为了解复用而设计的,RTMP文档上说的相当的模糊,message stream ID可以使任意值,不同的消息流复用成相同的chunk stream,基于它们的ID能够解复用。于chunk stream 是相关的,这个字段是一个不透明的值没有整明白什么意思,我的理解就是用来标识和服务器连接的flash端的序号。
    长度是7 bytes 的chunk head,该类型不包含stream ID,该chunk的streamID和前一个chunk的stream ID是相同的,变长的消息,例如视频流格式,在第一个新的chunk以后使用这种类型,注意其中时间戳部分是相对时间,为何上一个绝对时间之间的差值 如图所示:

     ++++++++++++++++++++++++++++++++++++++++++++++++++++++
    
    + timestamp delta+message length+ message type  id +             
    
    ++++++++++++++++++++++++++++++++++++++++++++++++++++++

    3 bytes的chunk head,该类型既不包含stream ID 也不包含消息长度,这种类型用于stream ID和前一个chunk相同,且有固定长度的信息,例如音频流格式,在第一个新的chunk以后使用该类型。如图所示:

     ++++++++++++++++++++
    
    + timestamp delta+          
    ++++++++++++++++++++

    0 bytes的chunk head,这种类型的chunk从前一个chunk得到值信息,当一个单个消息拆成多个chunk时,这些chunk除了第一个以外,其他的都应该使用这种类型,

    chunk的长度:
    chunk 的长度初始长度固定为128个字节,但是这个值并不是不可变的,在客户端和服务端建立连接以后,客户端和服务端都可以通过发送信令的方式来通知对端修改 chunk的长度,理论上来说可以修改chunk的最长长度为65536。这里chunk的长度是指chunk的数据部分的长度,即chunk data(payload)的长度,如果一条Message的数据长度超过了chunk的长度,就必须把Message分割成多条chunk,即如果一条 视频类型Message长度为2000个byte,chunk长度为1500,则该Message将会分割成两条chunk,第一条的chunk data长度为1500,第二条的chunk data长度为500。当然这两条chunk的chunk head肯定是不同的,其中第二条chunk的chunk head就是0字节的。

    rtmp负载数据格式分析

    信令格式

    Rtmp信令格式是amf格式(官方文档:amf3_spec_121207.pdf)。简单介绍下:
      AMF是Action Message Format的简写,它是一种二进制的数据格式, 它的设计,是为了把actionscript里面的数据(包括Object, Array, Boolean, Number等)序列化成 一段你基本看不大懂的二进制数据, 然后你可以把这段数据随意发送给其他地方的程序,比如发给远程的服务器, 在远程服务器那边, 又可以把这段数据给还原出来。以此达到一个数据传输的作用。Amf有amf0和amf3两个版本。AMF3消息流基本上都是在AMF3外面包了一层AMF0, 也就是说我们看到的所有AMF数据流都是AMF0的。

    一段AMF消息流解析如下:

    00 03 表示版本号为3, 其实个人觉得这个版本号用处不大,只是可以提醒你数据流中可能会遇到AMF3的数据
    00 00 表示头部的个数为0, 一般情况下貌似头部个数都是0,我还没理解什么情况下要用到头部,如果头部个数为n,那么接下来应该是n个头部的数据,这里因为n=0,所以直接跳过
    00 01 表示消息体的个数为1
    接下来就是(消息体的正文=targetURI+responseURI+内容长度+内容)* n,我们这个例子里n=1
    targetURI是一个字符串,它表示这个消息要发到哪里去,在这个例子里它 = amfService.dispatchAMF,responseURI也是一个字符串,它其实就类似于一个token的作用,因为我们同时可能调用了很多个service,那么service返回回来的数据要回调哪个处理函数呢?关键就在于这个responseURI,这个字符串会跟着数据流发出去, 然后还会回来。AMF0规定了targetURI和responseURI都是一个UTF字符串, 也就是用2个字节来表示字符串长度,后面紧接着字符串正文。  
    继续往下看
    00 16 表示targetURI的长度是0×16,
    61 6D……41 4D 46 就是targetURI的值: amfService.dispatchAMF
    00 03 表示responseURI的长度是3
    2F 36 34 表示responseURI的值: /64
    00 00 00 4D 表示后面的内容长度为0x4D
    接下来的都是内容正文了,内容正文的数据全是AMF0的的数据
    AMF的数据都是一个字节表示type(文档中称之为maker),然后紧接着数据
    0A 表示这个是一个标准的Array
    00 00 00 02 表示数组有2个元素
    02 表示第一个元素的type是字符串,
    00 30 表示第一个元素的字符串的长度是0×30
    32 … 33 37 表示的是字符串的值
    00 表示第2个元素是一个Number
    40 00 00 00 00 00 00 00 表示的就是这个Number的值

    上面这个例子正好不含有AMF3的数据,说明了开头的那个版本号3其实并没有太大意义,我们现在看到的数据都是AMF0的。

    媒体流格式

      Rtmp媒体流格式可以看成是flv里面video tag格式里面的data的格式。(官方文档:video_file_format_spec_v10_flv_f4v.pdf)。简单介绍下:

    第1个字节包含视频数据的参数信息
    第1个字节的前4位的数值表示帧类型
    第1个字节的后4位的数值表示视频编码ID,1 = JPEG(现已不用),2 = Sorenson H.263,3 = Screen video,4 = On2 VP6,5 = On2 VP6 with alpha channel,6 = Screen video version 2。

    从第2个字节开始为视频流数据。格式为AVCVIDEOPACKET

    第一个字节为AVCPacketType, 0: AVC sequence header 1: AVC NALU 2: AVC end of sequence

    第2,3,4个字节为CompositionTime 一般为0即可

    接下来的就是数据部分了。

    rtmp服务的实现

      由于我们的项目主要是放在设备上的,对项目的大小及语言有要求,因此就不能直接 一些开源的项目,现在是基于rtmpdump里面的一个rtmpsvr.c实现的rtmp服务端。Rtmpdump是一个rtmp客户端, rtmpsvr.c是rtmpdump里面附带的用于它自己测试的。

    主要流程包括:

    1、HandShake
      需要注意的是:RTMP Specifiction 1.0文档已经过时,从大概Adobe Flash Player 10.0.32.18版本开始,HandShake已不按该文档进行,文档中MUST be all 0的字节被填上了数据。当HandShake数据是这样时,要求回应的结尾有特定的数据,否则Adobe Flash Player将关闭H264/AAC的解码功能。Rtmpdump里面有实现握手,具体实现可以参考它

    2、信令交互
      交互的信令如下图所示:信令的格式参考 第三节的信令格式。
    rtmp交互的信令

    3、流数据传输
      开始是流相关的信令交互,然后就是流数据了,如下图所示:
    rtmp流数据

    流的格式参考 第三节的媒体流格式。

    一些RTMP项目,有Server端也有Client端

     · Red5 only contains a server-implementation (in java).
    
    · The python project rtmpy aims to be a free
    software implementation of an RTMP library, whilst Tape intends to be a full
    streaming server (in Python).  rtmpy is in active development.
    
    · There is a java client implementation of RTMP, called Flazr.
    As of 2nd June 2009 (just two weeks after Adobe issued the take-down notice),
    Flazr also has RTMPE support.
    Congratulations to Peter, and thank you to Adobe: none of this would have
    remotely happened, if you hadn't brought RTMPE to people's attention.
    
    · SWFDechas a partial and experimental implementation of RTMP.
    swfdec is client-only.
    
    · Gnashhas a partial and experimental implementations of RTMP.
    Gnash has both client and server, sharing the same common source.  Cygnal
    is making particularly good progress, as a server: video can already be
    streamed from it, with real-time video planned for Q3 2009.
    
    · libRTMPby boxee contains an RTMP client library, and was used as
    the basis for rtmpdump.
    
    · haxeVideois a server implementation of RTMP in Haxe.
    
    · crtmpserveris a server implementation of RTMP that has implemented
    (as of 25th may 2009) the RTMPE protocol.
    
    · Mammoth, formerly known as OpenFMS, is a server implementation
    that has implemented an RTMPE-compatible algorithm known as
    "H264-compatible and DH handshaking".
    
    · RubyIzumiis an implementation of an RTMP server in Ruby.
    
    · rtmpdump此项目是第一个突破RTMPE加密协议的,但因为破解了RTMPE所以惹恼了ADOBE,这个开源项目在SourceForge里已经没有了。但是作者的页面还保留有链接和代码。
    
    · http://rtmpd.com/ 这个项目极其庞大,还没有一些深入的了解
    
    flvstreamer  http://savannah.nongnu.org/projects/flvstreamer/
    
    Wowza    http://www.wowza.com/lp2?network=d&ad=15567605046&keyword=media+server&matchtype=&placement=thompsonng.blogspot.com&experiment=&mobile=&gclid=CN21xYDU2rQCFaN_Qgod9RQAXw


    2013年1月

    转载于:https://www.cnblogs.com/rongpmcu/p/7662200.html

    展开全文
  • 服务端的开发相对来说比客户端稍微难一点,也就是给填充相关结构体的时候,需要一点一点的去查阅,验证各个结构中各个成员各自代表什么意思,以及对应的功能需要是那个接口实现,这是开发服务端最头疼的事情。...

    服务端的开发相对来说比客户端稍微难一点,也就是给填充相关结构体的时候,需要一点一点的去查阅,验证各个结构中各个成员各自代表什么意思,以及对应的功能需要是那个接口实现,这是开发服务端最头疼的事情。(在开发过程中郁闷了好久,后面是通过搜索工具抓包海康设备来填充相关信息的)开始切入主题了,准备服务端的开发了。

    同理需要前面生成的代码,这个时候较之客户端的开发,需要在代码生成的时候之前生成的soapServer.c文件了,当放在客户端测试目录下用makefile编译的时候,你可能会很惊讶,怎么这么多错误,这么多函数报错,而且都是没有定义呢?

    别紧张,这些接口就是服务端开发需要实现的!即使开发不需要使用,但是根据onvif协议,也是需要给函数一个实现体的,具体的这些函数就需要看看soapServer.c文件里的soap_serve_request函数,这里我贴出来一部分如下:

     

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1.  ifndef WITH_NOSERVEREQUEST  
    2. SOAP_FMAC5 int SOAP_FMAC6 soap_serve_request(struct soap *soap)  
    3. {  
    4.     soap_peek_element(soap);  
    5.     if (!soap_match_tag(soap, soap->tag, "wsdd:Hello"))  
    6.         return soap_serve___wsdd__Hello(soap);  
    7.     if (!soap_match_tag(soap, soap->tag, "wsdd:Bye"))  
    8.         return soap_serve___wsdd__Bye(soap);  
    9.     if (!soap_match_tag(soap, soap->tag, "wsdd:Probe"))      
    10.         return soap_serve___wsdd__Probe(soap);  
    11.     if (!soap_match_tag(soap, soap->tag, "wsdd:ProbeMatches"))      
    12.         return soap_serve___wsdd__ProbeMatches(soap);  
    13.     if (!soap_match_tag(soap, soap->tag, "wsdd:Resolve"))      
    14.         return soap_serve___wsdd__Resolve(soap);  
    15.     if (!soap_match_tag(soap, soap->tag, "wsdd:ResolveMatches"))      
    16.         return soap_serve___wsdd__ResolveMatches(soap);  
    17.     if (!soap_match_tag(soap, soap->tag, "ns1:GetSupportedActions"))      
    18.         return soap_serve___ns1__GetSupportedActions(soap);      
    19.     if (!soap_match_tag(soap, soap->tag, "ns1:GetActions"))      
    20.         return soap_serve___ns1__GetActions(soap);  
    21.     if (!soap_match_tag(soap, soap->tag, "ns1:CreateActions"))      
    22.         return soap_serve___ns1__CreateActions(soap);  
    23.     if (!soap_match_tag(soap, soap->tag, "ns1:DeleteActions"))      
    24.         return soap_serve___ns1__DeleteActions(soap);  
    25.     if (!soap_match_tag(soap, soap->tag, "ns1:ModifyActions"))      
    26.         return soap_serve___ns1__ModifyActions(soap);  
    27.     if (!soap_match_tag(soap, soap->tag, "ns1:GetServiceCapabilities"))      
    28.         .  
    29.         .  
    30.          .  
    31.        //当然了,后来还有很长,很多了,具体实际开发可以根据需要来实现对应的函数体就好了  
    32.            

     

    后面还有很多系列函数,都是在对应了接口中调用了需要服务端实现的接口函数,代码框架只是有申明,没有实现,所以开发服务端的第一步,就是需要根据这里,把所以报错没有实现的函数全部实现掉,但是给一个函数体就好,后期开发再确定需要实现那些功能,再一个一个的接口具体实现,所以接下来就是写代码了,即使是拷贝复制工作,你也会有一种手要断了的赶觉的。我记得当时我就是一个整个下午在ctrl+ v 选中,然后p 粘贴.最后弄完眼睛都花了。

    因为每个函数的可以用相同的函数体来实现,所以写一个简单宏来代替是比较方面而且直观的方法,我的实现如下:

     

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. #define ONVIF_NOT_IMPLEMENTED_FUNC(soap, namespaces) \  
    2.     if( namespaces != NULL) \  
    3.         soap_set_namespaces(soap, namespaces); \  
    4.     printf("Func: %s, Path: %s \n", __func__, soap->path); \  
    5.     return soap_receiver_fault_subcode(soap, "test:Action Not Supported", "Test: Not Implemented ", "The requested action is not implemented ");  

    好了有了前面的准备工作开始写发现函数了,设备端的回复搜索的接口函数为__wsdd__Probe__wsdd__Probe,实现如下:

     

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. int SOAP_FMAC6  __wsdd__Probe(struct soap* soap, struct wsdd__ProbeType *wsdd__Probe)  
    2. {  
    3.     printf(" \n ##### Start __wsdd__Probe ##### \n");  
    4.     char _IPAddr[64] = {0};  
    5.     char _HwId[256] = {0};  
    6.   
    7.     wsdd__ProbeMatchesType ProbeMatches;  
    8.     ProbeMatches.ProbeMatch = (struct wsdd__ProbeMatchType *)soap_malloc(soap, sizeof(struct wsdd__ProbeMatchType));  
    9.     memset(ProbeMatches.ProbeMatch, 0,  sizeof(struct wsdd__ProbeMatchType));  
    10.   
    11.     ProbeMatches.ProbeMatch->XAddrs = (char *)soap_malloc(soap, sizeof(char) * 256);  
    12.     memset(ProbeMatches.ProbeMatch->XAddrs, '\0', sizeof(char) * 256);  
    13.   
    14.     ProbeMatches.ProbeMatch->Types = (char *)soap_malloc(soap, sizeof(char) * 256);  
    15.     memset(ProbeMatches.ProbeMatch->Types, '\0', sizeof(char) * 256);  
    16.   
    17.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceProperties = (struct wsa__ReferencePropertiesType*)soap_malloc(soap,sizeof(struct wsa__ReferencePropertiesType));  
    18.     memset(ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceProperties, 0, sizeof(struct wsa__ReferencePropertiesType));  
    19.   
    20.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceParameters = (struct wsa__ReferenceParametersType*)soap_malloc(soap,sizeof(struct wsa__ReferenceParametersType));  
    21.     memset(ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceParameters, 0, sizeof(struct wsa__ReferenceParametersType));  
    22.   
    23.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName = (struct wsa__ServiceNameType*)soap_malloc(soap,sizeof(struct wsa__ServiceNameType));  
    24.     memset(ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName, 0, sizeof(struct wsa__ServiceNameType));  
    25.     ProbeMatches.ProbeMatch->wsa__EndpointReference.PortType = (char **)soap_malloc(soap, sizeof(char *) * 256);  
    26.     memset(ProbeMatches.ProbeMatch->wsa__EndpointReference.PortType, 0, sizeof(char *) * 256);  
    27.   
    28.     ProbeMatches.ProbeMatch->wsa__EndpointReference.__any = (char **)soap_malloc(soap, sizeof(char*) * 256);  
    29.     memset(ProbeMatches.ProbeMatch->wsa__EndpointReference.__any, 0, sizeof(char*) * 256);  
    30.     ProbeMatches.ProbeMatch->wsa__EndpointReference.__anyAttribute = (char *)soap_malloc(soap, sizeof(char) * 256);  
    31.     memset(ProbeMatches.ProbeMatch->wsa__EndpointReference.__anyAttribute, 0,  sizeof(char) * 256);  
    32.   
    33.     ProbeMatches.ProbeMatch->wsa__EndpointReference.Address = (char *)soap_malloc(soap, sizeof(char) * 256);  
    34.     memset(ProbeMatches.ProbeMatch->wsa__EndpointReference.Address, 0, sizeof(char) * 256);  
    35.   
    36.   
    37.     //这里是一个uid,我在实际开发的过程中是的设备的本身mac地址,这里我取了一个mac地址的地址  
    38.      strcpy(_HwId, "urn:uuid:20131228-AABB-CCDD-EEFF-010203040506");  
    39.     //这是是需要回复给给客户端的基本信息.设备的ip地址以及通信端口  
    40.     sprintf(_IPAddr, "http://%d.%d.%d.%d:%d/onvif/device_service", 192,168,12,103, 8899);  
    41.   
    42.     ProbeMatches.__sizeProbeMatch = 1;  
    43.     ProbeMatches.ProbeMatch->Scopes = (struct wsdd__ScopesType*)soap_malloc(soap, sizeof(struct wsdd__ScopesType) * ProbeMatches.__sizeProbeMatch);  
    44.     memset(ProbeMatches.ProbeMatch->Scopes, 0, sizeof(struct wsdd__ScopesType) * ProbeMatches.__sizeProbeMatch);  
    45.     //Scopes MUST BE  
    46.     ProbeMatches.ProbeMatch->Scopes->__item =(char *)soap_malloc(soap, 1024);  
    47.     memset(ProbeMatches.ProbeMatch->Scopes->__item, '\0', 1024);  
    48.     strcat(ProbeMatches.ProbeMatch->Scopes->__item, "onvif://www.onvif.org/type/Network_Video_Transmitter ");  
    49.     strcat(ProbeMatches.ProbeMatch->Scopes->__item, "onvif://www.onvif.org/type/video_encoder ");  
    50.     strcat(ProbeMatches.ProbeMatch->Scopes->__item, "onvif://www.onvif.org/type/audio_encoder ");  
    51.     strcat(ProbeMatches.ProbeMatch->Scopes->__item, "onvif://www.onvif.org/location/city/CSDN ");  
    52.     strcat(ProbeMatches.ProbeMatch->Scopes->__item, "onvif://www.onvif.org/name/csder ");  
    53.     strcat(ProbeMatches.ProbeMatch->Scopes->__item, "onvif://www.onvif.org/hardware/TEST_Onvif ");  
    54.   
    55.     ProbeMatches.ProbeMatch->Scopes->MatchBy = NULL;  
    56.     strcpy(ProbeMatches.ProbeMatch->XAddrs, _IPAddr);  
    57.     strcpy(ProbeMatches.ProbeMatch->Types, wsdd__Probe->Types);  
    58.     printf("wsdd__Probe->Types=%s\n",wsdd__Probe->Types);  
    59.     ProbeMatches.ProbeMatch->MetadataVersion = 1;  
    60.   
    61.     //ws-discovery规定 为可选项  
    62.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceProperties->__size = 0;  
    63.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceProperties->__any = NULL;  
    64.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceParameters->__size = 0;  
    65.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ReferenceParameters->__any = NULL;  
    66.   
    67.     ProbeMatches.ProbeMatch->wsa__EndpointReference.PortType[0] = (char *)soap_malloc(soap, sizeof(char) * SMALL_256);  
    68.     //ws-discovery规定 为可选项  
    69.     strcpy(ProbeMatches.ProbeMatch->wsa__EndpointReference.PortType[0], "ttl");  
    70.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName->__item = NULL;  
    71.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName->PortName = NULL;  
    72.     ProbeMatches.ProbeMatch->wsa__EndpointReference.ServiceName->__anyAttribute = NULL;  
    73.     ProbeMatches.ProbeMatch->wsa__EndpointReference.__any[0] = (char *)soap_malloc(soap, sizeof(char) * SMALL_256);  
    74.     strcpy(ProbeMatches.ProbeMatch->wsa__EndpointReference.__any[0], "Any");  
    75.     strcpy(ProbeMatches.ProbeMatch->wsa__EndpointReference.__anyAttribute, "Attribute");  
    76.     ProbeMatches.ProbeMatch->wsa__EndpointReference.__size = 0;  
    77.     strcpy(ProbeMatches.ProbeMatch->wsa__EndpointReference.Address, _HwId);  
    78.       
    79.     soap->header->wsa__To = (char *)"http://schemas.xmlsoap.org/ws/2004/08/addressing/role/anonymous";  
    80.     soap->header->wsa__Action = (char *)"http://schemas.xmlsoap.org/ws/2005/04/discovery/ProbeMatches";  
    81.     soap->header->wsa__RelatesTo = (struct wsa__Relationship*)soap_malloc(soap, sizeof(struct wsa__Relationship));  
    82.     soap->header->wsa__RelatesTo->__item = soap->header->wsa__MessageID;  
    83.     soap->header->wsa__RelatesTo->RelationshipType = NULL;  
    84.     soap->header->wsa__RelatesTo->__anyAttribute = NULL;  
    85.   
    86.     soap->header->wsa__MessageID =(char *)soap_malloc(soap, sizeof(char) * 256);  
    87.     strcpy(soap->header->wsa__MessageID,_HwId+4); //前面四个字节可以是不需要的  
    88.   
    89.   
    90.     if (SOAP_OK == soap_send___wsdd__ProbeMatches(soap, "http://", NULL, &ProbeMatches))  
    91.     {  
    92. //      printf("send ProbeMatches success !\n");  
    93.         return SOAP_OK;  
    94.     }  
    95.   
    96.     printf("[%d] soap error: %d, %s, %s\n", __LINE__, soap->error, *soap_faultcode(soap), *soap_faultstring(soap));  
    97.     return soap->error;;  
    98.   
    99. }  

    搜索的回复函数本分就完成了,现在需要要的工作就是在设备端开启一个udp的socket了。为了不影响设备端其他的业务,所以建议设备端另外开一个线程让socket运行起来,因为这个是一个一直循环的操作了,基本的代码如下:

     

     

    [cpp] view plain copy
     
     在CODE上查看代码片派生到我的代码片
    1. int Onvif_DeviceDiscovery()  
    2. {  
    3.     struct soap udp_soap;  
    4.     int retval = -1;  
    5.   
    6.     soap_init1(&udp_soap, SOAP_IO_UDP | SOAP_IO_FLUSH);  
    7.     udp_soap.connect_flags = SO_BROADCAST;  
    8.     udp_soap.port = 3702;  
    9.   
    10.     soap_set_namespaces( &udp_soap, namespaces);  
    11.     SOAP_SOCKET udp_sock = -1;  
    12.   
    13.     udp_soap->omode = SOAP_IO_UDP;  
    14.     udp_soap->bind_flags = SO_REUSEADDR;  
    15.   
    16.     udp_sock = soap_bind(udp_soap, NULL, udp_soap->port, 100);  
    17.     if( (udp_sock < 0) && (udp_sock == SOAP_INVALID_SOCKET))  
    18.     {  
    19.         close(udp_sock);  
    20.         printf(" soap_bind failed! %s \n", strerror(errno));  
    21.         return -1;  
    22.     }  
    23.     //这个接口设置一些广播的属性值,下面也有实现提出,  
    24.     retval = udp_add_multicast(&udp_soap);  
    25.     if(retval != 0 )  
    26.     {  
    27.         printf(" udp add multicast failed: %s \n", strerror(errno));  
    28.         return -1;  
    29.     }  
    30.     //每次都是在此循环中接收客户端发过来的广播请求,然后服务端调用__wsdd__Probe函数,返回服务端的一些基本信息  
    31.     while(1)  
    32.     {  
    33.         if( soap_serve( &udp_soap ) != 0)  
    34.         {  
    35.             soap_print_fault(&udp_soap, stderr);  
    36.         }  
    37.   
    38.         soap_destroy(&udp_soap);  
    39.         soap_end( &udp_soap);  
    40.     }  
    41.     soap_done(&udp_soap);  
    42.     return 0;  
    43. }     
    44. int udp_add_multicast( struct soap* socksoap)  
    45. {  
    46.     //  set a route for multicast traffic  
    47.     //  这个执行一个系统命令,之前一直无法被搜索到,后来查了资料才知道需要启动下  
    48.     system("route add -net 224.0.0.0 netmask 224.0.0.0 eth0");  
    49.     int loop;  
    50.     int retval = -1;  
    51.     struct ip_mreq mreqcon;  
    52.     loop = 1;  
    53.     //设置组播的属性  
    54.     retval = setsockopt(socksoap->master, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));  
    55.     if(retval != 0)  
    56.     {  
    57.         printf("setsockopt: IP_MULTICAST_LOOP failed! %s\n ", strerror(errno));  
    58.         return -1;  
    59.     }  
    60.   
    61.     //绑定组播的ip地址  
    62.     mreqcon.imr_multiaddr.s_addr = inet_addr("239.255.255.250");  
    63.     mreqcon.imr_interface.s_addr = htonl(INADDR_ANY);  
    64.     if( (signed int )mreqcon.imr_multiaddr.s_addr == -1)  
    65.     {  
    66.         printf("239.255.255.250 not a legal multicast address! %s\n", strerror(errno));  
    67.         return -1;  
    68.     }  
    69.     retval = setsockopt(socksoap->master, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreqcon, sizeof(mreqcon));  
    70.     if( retval != 0 )  
    71.     {  
    72.         printf("setsockopt: IP_ADD_MEMBERSHIP failed! %s\n ", strerror(errno));  
    73.         return -1;  
    74.     }  
    75.   
    76.     return 0;  
    77. }  

    完成这些代码之后,通过onvif搜索工具,搜索的结果图如下

    看到基本信息也就是上面代码中填写了!设备端的发现功能也就实现了!

    纵观前后,其实设备端的发现只是在已经有的代码框架基础上操作两步就好!

    1 创建socket,搭建广播接收回复服务

    2 实现__wsdd__Probe函数!

     

    提供大家一个不错的网站:onvif server

    展开全文
  • token是什么意思

    万次阅读 2019-01-28 08:14:33
    token是计算机术语:令牌,令牌是...使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的: 1.客户端使用用户名跟密码请求登录 2.服务端收到请求,去验证用户名与密码 3.验证...

    token是计算机术语:令牌,令牌是一种能够控制站点占有媒体的特殊帧,以区别数据帧及其他控制帧。token其实说的更通俗点可以叫暗号,在一些数据传输之前,要先进行暗号的核对,不同的暗号被授权不同的数据操作。

     

    使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。大概的流程是这样的:

    1.客户端使用用户名跟密码请求登录

    2.服务端收到请求,去验证用户名与密码

    3.验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端

    4.客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里

    5.客户端每次向服务端请求资源的时候需要带着服务端签发的 Token

    6.服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据

    展开全文
  • JSP(Java Server Pages)是由Sun Microsystems公司倡导、许多公司参与一起建立的一种动态网页技术标准。... 用JSP开发的Web应用是跨平台的,既能在Linux下运行,也能...网页还能通过tags和scriptlets访问存在于服务端的资
  • 请求被pending,pending是什么意思?

    千次阅读 2019-12-27 11:49:44
    在Chrome DevTools 开发者工具窗口中,请求被“pending”是什么意思? pending(挂起):网络处于挂起状态,指发送的请求是“进行中”的状态,但还没有接到服务端的响应。(这类似于debug模式下加断点,请求被阻止...
  • 利用CXF和服务端代码生成WSDL文件

    千次阅读 2017-04-25 19:54:10
    根据编写的客户端代码来生成wsdl文件 首先通过编写一个小案例,我们编写了服务端的代码,点击...这里有一个问题,不同浏览器看到的XML结构有些问题,什么意思呢,有些浏览器会自动加载一些文本和结构,比较综合了一
  • 这里指的可降级与服务器降级意思相近(主逻辑失败采用备用逻辑的过程),考虑到服务端渲染并发及高负载的问题,在主服务器无法提供正常服务的时候可降级为"低功耗模式",采用客户端渲染方式来减轻服务器负载。...
  • Javaweb-服务端与客户端的信息识别-Session与Cookie 文章目录Javaweb-服务端与客户端的信息识别-...什么叫Cookie Cookie翻译成中文是小甜点,小饼干的意思。在HTTP中它表示服务器送给客户端浏览器的小甜点。其...
  • 我的svn地址是什么在版本库的目录下的conf目录,打开svnserve.conf文件,去掉anon-access = read前面的#号和空格,最好anon-access = read前没有空格也去掉,然后把anon-access = read改为anon-access = none,意思...
  • 客户端是什么意思

    2016-06-28 08:32:00
    除了一些只在本地运行的应用程序之外,一般安装在普通的客户机上,需要与服务端互相配合运行。接受服务的另一方我们称为客户端。 转载于:https://www.cnblogs.com/xiaorui123/p/5622155.html...
  • 首先,从字面上理解,代理的意思是代替办理,就是一方委托另一方办事,在计算机网络的世界里,代理通常是指客户端与服务端之间的中介。 计算机网络中的代理又分为正向代理和反向代理,正向代理很简单,就是客户端不...
  • php是什么意思

    2016-09-23 08:39:38
    当一个访问者打开主页时,服务端便执行PHP的命令并将执行结果发送至访问者的浏览器中,这类似于ASP和CoildFusion,然而PHP和他们不同之处在于PHP开放源码和跨越平台,PHP可以运行在WINDOWS NT和多种版本的UNIX上。...
  • 网页劫持可以分为服务端劫持、客户端劫持、快照劫持、搜索劫持等等;表现形式可以是劫持跳转,也可以是劫持呈现的网页内容,目前被广泛应用于私服等暴利行业。 iis7网站监控 网站是否被劫持、DNS是否被污染、网站...
  • groupId和artifactId的意思什么 点击查看 项目名中的 ‘-’ 好像没了 可以自己加上 加上之后是这样的 点击finish 可能会出现上图右下角的提示 点击箭头指向的选项 首先导入父项目的依赖 <dependencyManageme...
  • 200(ok)表示:从客户端成功发出去请求到服务端了,服务端也接收到了这条请求并正确返回 3**类状态码称之为Redirection 状态码,表示需要客户端进行附加操作(如跳转。重定向) 4**类状态码称之为Error状态码,通常...
  • 在介绍状态码之前,要简单讲一下为什么要有状态码这个东西。计算机之间的通信以协议为共同基础,客户端和服务端都按照协议的约定进行通信。HTTP的状态码就在HTTP的协议内,规定了很多的状态。客户端请求服务端后,...
  • 请解释一下Java多线程回调是什么意思? 所谓回调,就是客户端程序c调用服务端程序s中的某个方法A,然后s又在某个时候反过来调用c中的某个方法B,对于c而言,这个B就叫做回调方法。 ...
  • 1.下载服务端代码 https://github.com/yioMe/nodejs_wx_aipay_api 并且根据教程搭建完成 2.下载安装监控app 注意:如果您监控软件未运行,用户依然会付款给您,钱依然会直接到您支付宝微信余额中,但是就不会有回调....
  • php是什么意思

    2015-01-09 09:59:30
    PHP是一个基于服务端来创建动态网站的脚本语言,PHP 继承自一个老的工程,名叫 PHP/FI。PHP/FI 在 1995 年由 Rasmus Lerdorf 创建,最初只是一套简单... ...当一个访问者打开主页时,服务端便执行PHP的命令并将执行
  • 几天鱼摸下来,心里也不是滋味,看着身边的同学一个个每天都在学这学那,搞得我也不是很好意思。于是趁着现在各种完全体的方案和框架还没出来之前,那我们把vue3.0的服务端搭一搭吧,自己写写还是很有意思的。 好了...
  • 分别代表是什么意思? 简单版 [ 100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息 200 OK 正常返回信息 201 Created 请求成功并且...
  • URL中的#是什么意思

    2020-12-04 11:27:19
    #号是客户端bai参数,#号之后的参du数就不会传zhi入到服务端,用dao于网页位置定位,zhuan 比如http://www.example.com/index.html#print 浏览器会shu自动聚焦到id='print'的区块,百度百科词条目录就是这么做的,...
  • 分别代表是什么意思? 简单版 [ 100 Continue 继续,一般在发送post请求时,已发送了http header之后服务端将返回此信息,表示确认,之后发送具体参数信息 200 OK 正常返回信息 201 Created 请求成功并且...
  • CGI 的英文全名是 Common Gateway Interface,即通用网关接口,是 Web 服务器调用外部程序时所使用的一种服务端应用的规范。早期的 Web 通信只是按照客户端请求将保存在 Web 服务器硬盘中的数据转发过去而已,这种...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 478
精华内容 191
关键字:

服务端什么意思