p2p sdk异步建连源码介绍

KKP2P SDK介绍

kkp2p sdk是库快科技(kkuai.com)研发的支持p2p通信的中间件,是一套与业务无关的通用的p2p sdk库,可以免费下载试用版本使用。
一句话概括其特点:支持面向登录账号进行网络编程。
即只要传入对端的账号id,应用层就能得到一个socket句柄fd,应用层通过读写该socket fd句柄和对端进行通信。

优秀特性说明
跨平台kkp2p的sdk库是由c语言开发,在linux、windows、android、ios等平台编译出了静态库,以及其他一些嵌入式平台也编译出了静态库,大家可以直接下载进行使用。云端服务是由golang语言开发,也支持在各种平台下编译出直接可以运行的程序,配置也比较简单,大家下载之后就可以按照官网文档说明自行进行部署。
体积小kkp2p不依赖于任何第三方库,编译出来的库只有500KB左右大小。
性能强在服务器上测试,P2P方式通信的速度可以超过10MB每秒;中转方式通信的速度取决于您云端服务器的带宽
易使用提供了类似于socket编程接口的kkp2p_connect、kkp2p_listen、kkp2p_accept、kkp2p_read、kkp2p_write几个核心函数,使用起来非常简单方便。您只要指定对端的登录账号通过kkp2p_connect函数就能和对端创建一个虚拟的传输管道,然后通过kkp2p_read和kkp2p_write函数来读写数据和对端进行通信。您还可以通过参数指定是使用P2P方式通信还是使用中转(relay)方式通信,完全不用关心底层传输通道的创建和管理细节,一切由kkp2p的sdk库帮您解决。
高安全支持加密通道传输,您只需要在kkp2p_connect的参数中指定需要加密数据即可。sdk会自动创建一个加密的虚拟通信管道出来;您写入明文,sdk会自动加密成密文传输;sdk收到密文,会自动解密成明文返回给您。通信双方的共同密钥是双方的sdk通过DH算法自动协商而成,外界无法获取;并且每次sdk的启动都会自动协商生成一个新的动态密钥,严格保障您的通信数据的安全。如果您为了提升数据传输的性能,不想对数据进行加解密,只需要在创建连接的函数kkp2p_connect参数中指定不需要加密数据即可。sdk的数据加解密功能只有在商业版本中才有,在个人试用版本中没有该功能
通用性kkp2p是一套适用于各种场景的通用的通信中间件,会完全透传用户的数据,您可以灵活的自定义通信双方的协议,kkp2p不会解析您的业务数据。kkp2p的P2P通信是基于udp实现的,kkp2p会自动帮您解决丢包、乱序、重传问题,也会根据您的实际带宽做自适应的带宽流控,您使用起来具有tcp传输的效果,相当于是用udp模拟实现了tcp。中转(relay)通信是基于tcp原生实现的。

异步建连源码

该p2p sdk中间件提供了异步建立连接接口,用来支持高性能程序编写。本文档主要讲解其源码,该源码在linux平台下编译测试通过。

源码

#include <stdio.h>
#include <stdint.h>
#include <errno.h>
#include <sys/stat.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include<stdlib.h>
#include <sys/time.h>
#include <time.h>

// 去kkuai.com 免费获取试用
// 得包含kkp2p sdk的头文件,以及链接libkkp2p.a
#include "kkp2p_sdk.h"

// 传给engine层的自定义参数,方便实现回掉逻辑
// fd是管道描述符
// channel是业务层指针,用户保存回掉函数中的channel信息
struct ConnParam {
    int fd;
    kkp2p_channel_t* channel;
};

void ConnectCallBack(int result, kkp2p_channel_t* channel, void* param) {
    // 自定义回掉函数,由engine层线程创连结束后回掉
    struct ConnParam* connParam = (struct ConnParam*)param;
    if (result < 0) {
        // result小于0表示创建连接失败,写入管道-1
        char ch = -1;
        write(connParam->fd, &ch, 1);
    } else {
        // 创建连接成功,写入管道0
        char ch = 0;
        write(connParam->fd, &ch, 1);
    }
    // 保存返回的channel信息,里面有peerId,以及连接相关的信息,比如是P2P传输连接,还是中转传输连接等
    memcpy(connParam->channel, channel, sizeof(kkp2p_channel_t));
}

int main(int argc, char** argv)
{
    // 需要输入两个参数,一个是对方的登录peerId,另外一个是希望的连接类型
    // 0 自动模式,p2p和中转谁创建的快就用谁
    // 1 仅P2P模式
    // 2 仅relay模式
    if (argc < 3) {
        printf("usage:%s peerId,connMode\n",argv[0]);
        return -1;
    }

    // 初始化kkp2p sdk的配置信息
    // 包括云端的登录信息,局域网侦听端口以及日志信息
    kkp2p_engine_conf_t kkp2p_conf;
    kkp2p_conf.login_domain = "125.72.218.199";
    kkp2p_conf.login_port = 3080;
    kkp2p_conf.lan_search_port = 3549;
    kkp2p_conf.max_log_size = 1024*1024*10;
    kkp2p_conf.log_path = NULL;
    kkp2p_engine_t* p2pEngine = kkp2p_engine_init(&kkp2p_conf, 5000);
    if (p2pEngine == NULL) {
        printf("init kkp2p engine error.\n");
        return -1;
    }
    
    // 切换日志级别,4为debug级别
    kkp2p_switch_log_level(p2pEngine, 4);

    char* peerId = argv[1];

    // 创建管道,业务层读管道,创连结束后的回掉函数中写管道
    int pipefd[2] = {0};
    int ret = pipe(pipefd);
    if (ret == -1)
    {
        printf("pipe error.\n");
        return -1;
    }
    // 申请一个channel,用于保存回掉函数返回的channel信息
    kkp2p_channel_t channel;
    
    // 传给回掉函数的自定义参数
    ConnParam connParam;
    connParam.channel = &channel;
    connParam.fd = pipefd[1];

    // 建连参数,包括对端peerId,以及超时时间
    kkp2p_connect_ctx_t ctx;
    memset(&ctx, 0, sizeof(ctx));
    strncpy(ctx.peer_id, peerId, 32);
    ctx.connect_mode = atoi(argv[2]);
    
    // 不使用加密连接
    ctx.encrypt_data = 0;
    
    // 建连超时时间
    ctx.timeout = 2000;
    
    // 传入回掉函数的指针以及自定义回掉函数参数,如果指针为空则使用的是同步建连模式
    // 异步建连
    ctx.func = ConnectCallBack;
    ctx.func_param = &connParam;
    
    // 创建连接,该函数返回之后只是向engine层发送建连请求成功
    kkp2p_connect(p2pEngine, &ctx, &channel);
    char ch = -1;
        // 计算建连开始时间,方便统计建连耗时
    struct timeval startT;
    gettimeofday(&startT, NULL);
    uint64_t startM = (uint64_t)startT.tv_sec * 1000 + (uint64_t)startT.tv_usec / 1000;
    
    // 业务层开始读管道,如果管道没有数据,会一直阻塞
    read(pipefd[0],&ch,1);
        
    // 读到管道数据,-1标识建连失败,0标识建连成功,看回掉函数自定义实现,并计算建连结束时间
    struct timeval endT;
    gettimeofday(&endT, NULL);
    uint64_t endM = (uint64_t)endT.tv_sec * 1000 + (uint64_t)endT.tv_usec / 1000;    
    if (ch < 0) {
        // 建连失败
        printf("connect %s error,cost %llu millisecond.\n",channel.peer_id,endM-startM);
    } else {
        // 建连成功,并打印连接相关的信息,通过读写channel.fd即可以和对端进行通信
        // 最后关闭连接的代理fd句柄和连接
        printf("connect %s success,channel id:%u,channel fd:%u,cost %llu millisecond.\n",channel.peer_id, channel.channel_id, channel.fd, endM-startM);
        kkp2p_close_fd(channel.fd);
        kkp2p_close_channel(p2pEngine, channel.channel_id);
    }
    
    // 释放kkp2p sdk engine
    kkp2p_engine_destroy(p2pEngine);
    return 0;
}
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值