视频监控安防平台-GB28181_2016版-注册、心跳、注销

前段时间好几个项目在同时进行,整天忙的不可开交,尤其是项目上的雪亮工程项目需求太多了(而且是各种奇葩的需求,估计也是招投标为了限制其他公司的吧,很多功能都没有实际用处),也没用静下心来好好整理下GB28181相关内容,我准备从头整理一下相关信息,主要以28181检测项为索引来整理,下面我简单介绍下注册、心跳和注销这几个协议,注册和注销很好理解,就是Expires: 0的时候为注销,心跳也很简单就是一个简单的无应答message。

下面将注册的流程图简单摘出来一下:

根据流程图还是比较容易读懂,下面粘贴一下抓包信息:

REGISTER sip:34020000002000000001@192.168.1.81:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.93:5060;rport;branch=z9hG4bK-3d09000-23b5dfc-TFyCL5ME
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=pck2i7pI
To: <sip:64000000002000000001@192.168.1.93:5060>
Call-ID: b4359b71-eb2f-b6f4-2fce-8fd47e5888ff@192.168.1.93
CSeq: 5 REGISTER
Contact: <sip:64000000002000000001@192.168.1.93:5060>
Authorization: Digest username="34020000002000000001", realm="3402000000", nonce="bd2e4df9e3d9b280", uri="sip:64000000002000000001@192.168.1.93:5060", response="9c8411f2b96c5aef55eb136ba3f34655", algorithm=MD5
Max-Forwards: 70
User-Agent: iVMS 1.0
Expires: 200
Content-Length: 0SIP/2.0 401 Unauthorized
To: <sip:64000000002000000001@192.168.1.93:5060>;tag=67239569_53173353_7ce4590f-587d-4d44-9690-96498367c675
Via: SIP/2.0/UDP 192.168.1.93:5060;rport=5060;branch=z9hG4bK-3d09000-23b5dfc-TFyCL5ME;received=192.168.1.93
CSeq: 5 REGISTER
Call-ID: b4359b71-eb2f-b6f4-2fce-8fd47e5888ff@192.168.1.93
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=pck2i7pI
WWW-Authenticate: Digest realm="3402000000",nonce="31ada55697307236"
Content-Length: 0REGISTER sip:34020000002000000001@192.168.1.81:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.93:5060;rport;branch=z9hG4bK-3d09000-3068be5-lnl05y0C
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=pck2i7pI
To: <sip:64000000002000000001@192.168.1.93:5060>
Call-ID: b4359b71-eb2f-b6f4-2fce-8fd47e5888ff@192.168.1.93
CSeq: 6 REGISTER
Contact: <sip:64000000002000000001@192.168.1.93:5060>
Authorization: Digest username="34020000002000000001", realm="3402000000", nonce="31ada55697307236", uri="sip:64000000002000000001@192.168.1.93:5060", response="3526a5a5dd91a45e19d1e6a65704457f", algorithm=MD5
Max-Forwards: 70
User-Agent: iVMS 1.0
Expires: 200
Content-Length: 0SIP/2.0 200 OK
To: <sip:64000000002000000001@192.168.1.93:5060>;tag=86156704_53173353_d7fb589f-4357-4fae-ae32-47c38d81fff1
Via: SIP/2.0/UDP 192.168.1.93:5060;rport=5060;branch=z9hG4bK-3d09000-3068be5-lnl05y0C;received=192.168.1.93
CSeq: 6 REGISTER
Call-ID: b4359b71-eb2f-b6f4-2fce-8fd47e5888ff@192.168.1.93
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=pck2i7pI
Contact: <sip:64000000002000000001@192.168.1.93:5060>
Expires: 200
Date: 2017-05-19T18:09:17.033
Content-Length: 0

其中注册要注意的是,注册的时候有个回复时间格式需要进行上下级和设备之间校时功能:

Date: 2017-05-19T18:09:17.033

心跳:

MESSAGE sip:34020000002000000001@192.168.1.81:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.93:5060;rport;branch=z9hG4bK-3d09000-2a2b21b-nddru7fy
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=UL61Qycy
To: <sip:34020000002000000001@192.168.1.81:5060>
Call-ID: 5be796e4-b5ab-592e-cc13-64f34ea57528@192.168.1.93
CSeq: 35 MESSAGE
Contact: <sip:192.168.1.93:5060>
Content-Type: Application/MANSCDP+xml
Max-Forwards: 70
User-Agent: iVMS 1.0
Content-Length:   151<?xml version="1.0"?>
<Notify>
<CmdType>Keepalive</CmdType>
<SN>26</SN>
<DeviceID>64000000002000000001</DeviceID>
<Status>OK</Status>
</Notify>
SIP/2.0 200 OK
To: <sip:34020000002000000001@192.168.1.81:5060>;tag=69112542_53173353_89bb4bc2-7f74-42a8-a102-6b6490b6daa2
Via: SIP/2.0/UDP 192.168.1.93:5060;rport=5060;branch=z9hG4bK-3d09000-2a2b21b-nddru7fy;received=192.168.1.93
CSeq: 35 MESSAGE
Call-ID: 5be796e4-b5ab-592e-cc13-64f34ea57528@192.168.1.93
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=UL61Qycy
Content-Length: 0

注销:

REGISTER sip:34020000002000000001@192.168.1.81:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.93:5060;rport;branch=z9hG4bK-3d09000-23b5dfc-TFyCL5ME
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=pck2i7pI
To: <sip:64000000002000000001@192.168.1.93:5060>
Call-ID: b4359b71-eb2f-b6f4-2fce-8fd47e5888ff@192.168.1.93
CSeq: 5 REGISTER
Contact: <sip:64000000002000000001@192.168.1.93:5060>
Authorization: Digest username="34020000002000000001", realm="3402000000", nonce="bd2e4df9e3d9b280", uri="sip:64000000002000000001@192.168.1.93:5060", response="9c8411f2b96c5aef55eb136ba3f34655", algorithm=MD5
Max-Forwards: 70
User-Agent: iVMS 1.0
Expires: 0
Content-Length: 0SIP/2.0 401 Unauthorized
To: <sip:64000000002000000001@192.168.1.93:5060>;tag=67239569_53173353_7ce4590f-587d-4d44-9690-96498367c675
Via: SIP/2.0/UDP 192.168.1.93:5060;rport=5060;branch=z9hG4bK-3d09000-23b5dfc-TFyCL5ME;received=192.168.1.93
CSeq: 5 REGISTER
Call-ID: b4359b71-eb2f-b6f4-2fce-8fd47e5888ff@192.168.1.93
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=pck2i7pI
WWW-Authenticate: Digest realm="3402000000",nonce="31ada55697307236"
Content-Length: 0REGISTER sip:34020000002000000001@192.168.1.81:5060 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.93:5060;rport;branch=z9hG4bK-3d09000-3068be5-lnl05y0C
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=pck2i7pI
To: <sip:64000000002000000001@192.168.1.93:5060>
Call-ID: b4359b71-eb2f-b6f4-2fce-8fd47e5888ff@192.168.1.93
CSeq: 6 REGISTER
Contact: <sip:64000000002000000001@192.168.1.93:5060>
Authorization: Digest username="34020000002000000001", realm="3402000000", nonce="31ada55697307236", uri="sip:64000000002000000001@192.168.1.93:5060", response="3526a5a5dd91a45e19d1e6a65704457f", algorithm=MD5
Max-Forwards: 70
User-Agent: iVMS 1.0
Expires: 0
Content-Length: 0SIP/2.0 200 OK
To: <sip:64000000002000000001@192.168.1.93:5060>;tag=86156704_53173353_d7fb589f-4357-4fae-ae32-47c38d81fff1
Via: SIP/2.0/UDP 192.168.1.93:5060;rport=5060;branch=z9hG4bK-3d09000-3068be5-lnl05y0C;received=192.168.1.93
CSeq: 6 REGISTER
Call-ID: b4359b71-eb2f-b6f4-2fce-8fd47e5888ff@192.168.1.93
From: <sip:64000000002000000001@192.168.1.93:5060>;tag=pck2i7pI
Contact: <sip:64000000002000000001@192.168.1.93:5060>
Expires: 0
Date: 2017-05-19T18:09:17.033
Content-Length: 0

下面粘贴一下部分注册的代码,由于使用c++写的代码,所有只能裁剪一部分出来:

#include <stdlib.h>
#include <stdio.h>
#include "eXosip2/eXosip.h"
#include "osipparser2/osip_uri.h"
#include "osipparser2/osip_message.h"
#include "eXosip2.h"//初始化 监听端口
int Init(int listenport)
{int iRet = eXosip_init();if (iRet != OSIP_SUCCESS){//DBGPrint(M_SipUA, ERROR_LEVEL, "eXosip2 fail!");//return -1;printf("eXosip2 fail! \n");exit(1);}iRet = eXosip_listen_addr(IPPROTO_UDP, NULL, listenport, AF_INET, 0);if (iRet != OSIP_SUCCESS){eXosip_quit();//DBGPrint(M_SipUA, ERROR_LEVEL, "eXosip2 could not initialize transport layer!");//return -1;DBGPrint(M_SipUA, BREAK_LEVEL, "eXosip2 could not initialize transport layer! \n");exit(1);}DBGPrint(M_SipUA, BREAK_LEVEL, "%s: SipSvr Listen Port:%d Sucess!!!!", __FUNCTION__, listenport);return 0;
}/*******************************************************************************
* Function:
*   Digest MD5 authorization validate process.
*******************************************************************************/
//MD5鉴权
bool MD5AuthValidate(char *pMethod, osip_authorization_t *pAuthEcho)
{if (NULL == pAuthEcho){DBGPrint(M_SipUA, ERROR_LEVEL, "pAuthField is null pointer!");return false;}char *pAlgorithm  = NULL;char *pUsername   = NULL;char *pRealm      = NULL;char *pPasswd     = NULL;char *pNonce      = NULL;char *pNonceCount = NULL;char *pCNonce     = NULL;char *pQop        = NULL;char *pCMethod     = NULL;char *pUri        = NULL;char sNullAlg[]   = "";  //"MD5";char sNullQop[]   = "";  //"auth";char SessionKey[MD5_SESSION_KEY_LEN+1] = {0};char Response[MD5_RESPONSE_LEN] = {0};char *pResponse2  = NULL;if (NULL == pAuthEcho->algorithm)pAlgorithm = unquote(sNullAlg);elsepAlgorithm = unquote(pAuthEcho->algorithm);pUsername  = unquote(pAuthEcho->username);pRealm     = unquote(pAuthEcho->realm);pPasswd    = unquote(CSBase::m_SipRegPasswd);pNonce     = unquote(pAuthEcho->nonce);pCNonce    = unquote(pAuthEcho->cnonce);if (NULL == pUsername){DBGPrint(M_SipUA, ERROR_LEVEL, "%s Get username is null error!",__FUNCTION__);return false;}if(strcmp(pUsername, CSBase::m_SipRegUserName) != 0){//    DBGPrint(M_SipUA, ERROR_LEVEL, "%s %s username error!",__FUNCTION__,pAuthEcho->username);//    return false;}//calculate session keyDigestCalcHA1(pAlgorithm, pUsername, pRealm, pPasswd, pNonce, pCNonce, SessionKey);pNonceCount = unquote(pAuthEcho->nonce_count);if (NULL == pAuthEcho->message_qop)pQop = unquote(sNullQop);elsepQop = unquote(pAuthEcho->message_qop);pCMethod = unquote(pMethod);pUri    = unquote(pAuthEcho->uri);//calculate responseDigestCalcResponse(SessionKey, pNonce, pNonceCount, pCNonce, pQop, pCMethod, pUri, (char*)"", Response);pResponse2  = unquote(pAuthEcho->response);if (strcmp(Response, pResponse2) != 0){DBGPrint(M_SipUA, ERROR_LEVEL, "Authorization failed <%s, %s>!", Response, pResponse2);return false;}return true;
}//回复没有包体的响应
int SendRegisterAnswer(int Tid, int Code, bool bSetTime)
{osip_message_t * pMsgAnswer = NULL;int ret = eXosip_message_build_answer(Tid, Code,&pMsgAnswer);if(ret == OSIP_SUCCESS && pMsgAnswer != NULL ){if (bSetTime == true){osip_header_t*  pHeader = NULL;char            TmpBuf[CLIP_BUFFER_SIZE+1];//initialize Date headerint iRet = osip_header_init(&pHeader);if (OSIP_SUCCESS == iRet){time_t now;struct timeval tv;//Get current timegettimeofday(&tv,NULL);now = tv.tv_sec;//           time(&now);//struct tm* pTmVal = localtime(&now);struct tm STm = {0};struct tm* pTmVal = localtime_r(&now, &STm);  //使用线程安全函数if (pTmVal != NULL){//系统启用夏令时,需要减去一个小时。if (1 == pTmVal->tm_isdst){now -= 3600;//pTmVal = localtime(&now);pTmVal = localtime_r(&now, &STm);  //使用线程安全函数if (NULL == pTmVal)return -1;}//2010-07-26 16:05:10snprintf(TmpBuf, CLIP_BUFFER_SIZE, "%4d-%02d-%02dT%02d:%02d:%02d.%03d", pTmVal->tm_year+1900, pTmVal->tm_mon+1, pTmVal->tm_mday, pTmVal->tm_hour, \pTmVal->tm_min, pTmVal->tm_sec,(int)(tv.tv_usec/1000));//set Date fieldosip_header_set_name(pHeader, osip_strdup("Date") );osip_header_set_value(pHeader, osip_strdup(TmpBuf) );osip_list_add(&pMsgAnswer->headers, pHeader, -1);}}}eXosip_message_send_answer(Tid, Code, pMsgAnswer);}else{DBGPrint(M_SipUA, ERROR_LEVEL, "%s:Build Message Answer Failed Tid<%d> Code<%d>!", __FUNCTION__, Tid, Code);}return 0;
}//初始接收的注册信息
int ProceRegister(const eXosip_event_t* pSipEvt)
{int iReturnCode = -1;int iRet = -1;osip_authorization_t *pWWWAuEcho = NULL;iRet = osip_message_get_authorization(pSipEvt->request, 0, &pWWWAuEcho);if (iRet != -1){//鉴权, 鉴权成功回复200OKif (MD5AuthValidate(pSipEvt->request->sip_method, pWWWAuEcho)){//鉴权成功,回复200成功//添加用户信息SendRegisterAnswer(pSipEvt->tid, SIP_OK, true);}else{//鉴权失败,回复403SendRegisterAnswer(pSipEvt->tid, SIP_FORBIDDEN, false);}}else{//回复401 , 待认证osip_www_authenticate_t *pWWWAuth = NULL;iRet = osip_www_authenticate_init(&pWWWAuth);if (-1 == iRet){DBGPrint(M_SipUA, ERROR_LEVEL, "Failed to init www-authenticate header");return -1;   }char RTag[RANDOM_TAG_LEN+1] = {0};char Nonce[DIGEST_NONCE_LEN+1] = {0};char TmpBuf[CLIP_BUFFER_SIZE/2+1] = {0};SIPGenerateNonce(Nonce, 0, GenerateRandomTag(RTag) );osip_www_authenticate_set_auth_type(pWWWAuth, osip_strdup("Digest") );memcpy(TmpBuf, CSBase::m_SipSvrPubID, 10);char realm[CLIP_BUFFER_SIZE];snprintf(realm, CLIP_BUFFER_SIZE/2, "\"%s\"", TmpBuf);osip_www_authenticate_set_realm(pWWWAuth, osip_strdup(realm) );snprintf(TmpBuf, CLIP_BUFFER_SIZE/2, "\"%s\"", Nonce);osip_www_authenticate_set_nonce(pWWWAuth, osip_strdup(TmpBuf) );char *pDest = NULL;osip_www_authenticate_to_str(pWWWAuth, &pDest);osip_message_t * pSRegister = NULL;iReturnCode = eXosip_message_build_answer(pSipEvt->tid,SIP_UNAUTHORIZED,&pSRegister);if ( iReturnCode == 0 && pSRegister != NULL ){osip_message_set_www_authenticate(pSRegister,pDest);osip_message_set_content_type(pSRegister,"Application/MANSCDP+xml");eXosip_message_send_answer(pSipEvt->tid,SIP_UNAUTHORIZED,pSRegister);}osip_www_authenticate_free(pWWWAuth);osip_free(pDest);        }return 0;
}int ProceXsipEvt(eXosip_event_t* pSipEvt)
{//Check input parameter exceptionif (NULL == pSipEvt){DBGPrint(M_SipUA, ERROR_LEVEL, "%s: pSipEvt is null pointer!", __FUNCTION__);return -1;}//Check eXosip event typeswitch (pSipEvt->type) {case EXOSIP_MESSAGE_NEW: if (MSG_IS_NOTIFY(pSipEvt->request)) {   //ProceNotify(pSipEvt);}else if(MSG_IS_MESSAGE(pSipEvt->request)){//ProceMessage(pSipEvt);}else if(MSG_IS_REGISTER(pSipEvt->request)){ProceRegister(pSipEvt);}break;case EXOSIP_SUBSCRIPTION_ANSWERED:case EXOSIP_SUBSCRIPTION_REQUESTFAILURE:{//ProcSubScribleAnswer(pSipEvt);   }break;case EXOSIP_SUBSCRIPTION_NOTIFY:{//ProceNotify(pSipEvt);}break;case EXOSIP_CALL_PROCEEDING:case EXOSIP_CALL_RINGING:break;case EXOSIP_CALL_ANSWERED:{    eXosip_call_t* pJCall = NULL;if (OSIP_SUCCESS == eXosip_call_find(pSipEvt->cid, &pJCall) ){   //ProcCallAnswer(pSipEvt);}}break;case EXOSIP_CALL_NOANSWER:case EXOSIP_CALL_REDIRECTED:case EXOSIP_CALL_REQUESTFAILURE:case EXOSIP_CALL_SERVERFAILURE:case EXOSIP_CALL_GLOBALFAILURE:case EXOSIP_CALL_TIMEOUT:{if (pSipEvt->request == NULL || pSipEvt->response == NULL){DBGPrint(M_SipUA, ERROR_LEVEL, "%s: Recv Sip Type<%d:%s> Error!", __FUNCTION__, pSipEvt->type, GetRecvSipType(pSipEvt->type));break;}DBGPrint(M_SipUA, ERROR_LEVEL, "%s: ******** receive device:<%s> error !response status code:<%d> username:<%s>!", __FUNCTION__, pSipEvt->request->to->url->username, pSipEvt->response->status_code, pSipEvt->request->req_uri->username );eXosip_call_t* pJCall = NULL;if (OSIP_SUCCESS == eXosip_call_find(pSipEvt->cid, &pJCall) ){//ProcCallAnswer(pSipEvt);}}break;case EXOSIP_CALL_MESSAGE_NEW:if (MSG_IS_BYE(pSipEvt->request) ){DBGPrint(M_SipUA, ERROR_LEVEL, "%s: ******** imcoming BYE for DevAor<%s>!", __FUNCTION__, CSBase::URIToAOR(pSipEvt->request->from->url) );}break;case EXOSIP_CALL_MESSAGE_ANSWERED://BYE responsebreak;case EXOSIP_CALL_CLOSED:break;case EXOSIP_CALL_RELEASED:break;case EXOSIP_MESSAGE_REQUESTFAILURE:break;case EXOSIP_MESSAGE_ANSWERED:break;default:DBGPrint(M_SipUA, ERROR_LEVEL, "%s: not handle <%d:%s> event type!", __FUNCTION__, pSipEvt->type, GetRecvSipType(pSipEvt->type));return -1;}
}int main()
{//初始化exosip协议栈端口Init(5060);//等待接收sip数据while(1){//---------------- eXosip running process ----------------//eXosip_execute();eXosip_event_t* pSipEvt = eXosip_event_wait(0, 50);while (pSipEvt != NULL){eXosip_lock();ProceXsipEvt(pSipEvt);eXosip_default_action(pSipEvt);eXosip_unlock();eXosip_event_free(pSipEvt);pSipEvt = eXosip_event_wait(0, 50);}usleep(50000); }}

视频监控安防平台-GB28181_2016版-注册、心跳、注销相关推荐

  1. 视频监控安防平台-国标28181平台(支持国标28181转RTSP/RTMP/HLS/WEBRTC直播)

    视频监控安防平台-国标28181平台(支持国标28181转RTSP/RTMP/HLS/WEBRTC直播) 发现很久都未更新博客了,最近把小平台的功能做了完善,在原来的功能基础上添加了功能,支持国标28 ...

  2. 视频监控安防平台(企业级)-国标28181平台

    很久没有更新博客了,最近在完善平台的改造,下面我把平台信息发布出来,可以对接国标28181平台.国标28181摄像机.NVR,平台接入量目前项目上使用最多是接入50W路摄像机,欢迎大家使用! 客户端登 ...

  3. 视频监控安防平台--国标28181-2016 GB28181-2016 平台全项检测经历

    国标28181-2016 GB28181-2016 平台全项检测经历        最近去北京公安一所帮公司检测国标28181-2016版平台的全项检测,由于之前是帮自己公司检测过一次国标28181- ...

  4. 【解决方案】5G时代浪潮来袭,EasyNVR助力5G厂区视频监控安防采集可视化展示

    智慧工厂被认为是5G技术的重要应用场景之一,利用5G网络将生产设备无缝连接,并进一步打通设计.采购.仓储.物流等环节,满足工业环境下设备互联和远程交互应用需求.TSINGSEE青犀视频面向工厂智能化升 ...

  5. 关于对接海康威视综合安防平台并使用SDK下载过车视频

    背景:现有多个摄像头点位和一个Secure Center综合安防管理平台,需要做一个功能,当有车辆经过监控点位时抓取一定时间段内的视频存储在服务器上用作分析.本文主要讲解如何根据官方给的SDK(Vid ...

  6. 海康安防平台监控画面通道命名修改

    新版海康安防平台监控画面通道命名 1.根据图片操作,完成记得保存.

  7. 海康综合安防平台使用内置H5播放器查看监控录像

    目录 一.说明 二.解决办法:安装根证书 (一)Windows平台 (二)Mac平台 一.说明 1.海康综合安防平台查看监控有三种方式.其一,使用客户端,仅支持Windows平台.其二,使用OCX控件 ...

  8. python概念股_python 股票 监控,安防监控概念股,新的安防监控概念股有哪些?

    python 股票 监控 在安防监控方面,之后在公安.交通.监狱.安监等领域实行"产品+系统集成"的销售模式,夯实以云贵川居多的区域性安防监控市场优势,为下一步扩展其他省市安防监控 ...

  9. ssm 远程监控linux,Wisenet SSM视频监控综合管理平台

    Wisenet SSM视频监控综合管理平台是一款智能控制终端软件,而Wisenet SSM由Console Client程序和Core Server组成,也就是视频的监控和视频的保存功能. Wisen ...

最新文章

  1. Intent和PendingIntent的区别
  2. 试试Linux下的ip命令,ifconfig已经过时了
  3. alter system flush shared_pool的作用 .
  4. spring+log4j
  5. 云+X案例展 | 民生类:贝斯平云助力500强跨国企数字化转型
  6. python flask高级编程之restful_python Flask实现restful api service
  7. win10环境,Eclipse安装Maven
  8. 我发现不少大有课堂的年轻学员确实在做自媒体
  9. R与Python手牵手:数据科学导论系列(包的载入)
  10. Access数据库迁移到MS SQL Server数据库
  11. mysql (1) 聚集索引和非聚集索引
  12. 自主导航小车实践(一)
  13. 2022年执法资格城管执法考试多选题专项训练题及答案
  14. 两化融合贯标之-申请表案例
  15. 阿里“无影” | 未来每个人在云上都会有自己的主机
  16. 从0开始一步一步部署walle
  17. oracle dbms_repair,DBMS_REPAIR包使用详解
  18. Vue-draggable 实现页面模板自动化
  19. 校办研修之计算机培训简报,校本教研培训简报_
  20. 信用风险评级模型的开发过程

热门文章

  1. vcruntime140_1.dll
  2. 编译原理学习-形式语言 乔姆斯基文法
  3. 无接触梯控模组及设备
  4. 扛把子级别的Java开源后台管理系统
  5. 蚂蚁金服高级前端专家,我做前端这 10 多年来的感悟
  6. flink 教程 Window
  7. MongoDB建模场景
  8. 泰山OFFICE技术讲座:同一行不同字号的字如何对齐绘制
  9. 办公OA系统毕业设计论文
  10. android反编译修改教程,反编译教程