导语
TUTK提供的P2PTunnel服务,类似于vpn服务。P2PTunnel服务启动后,将通过TUTK的私有协议,将上层传入的数据转发到对端,而且不需要知道对端的IP。
P2PTunnel模块,可以内嵌至厂商的程序内,也可以独立做成一个模块。对于一些基于TCP/IP的标准或者私有服务,比如http、ssh、ftp、telnet、rtsp,只需要简单几行代码,就可以完成接入。
P2PTunnel模块工作示意图
P2PTunnelServer使用流程图
例子代码分析
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搭建一个流媒体服务器