开源库 pjnath的改造,异步接口 修改 为 同步 超时返回 接口

本文介绍如何将开源库pjnath中的异步非阻塞函数转换为同步阻塞函数,特别是pj_ice_strans_create接口。通过在关键回调函数stun_on_status和turn_on_state中设置标志变量,实现在获取到完整网络候选信息后继续执行,避免因网络延迟导致的问题。这种方法提供了一种超时机制,既能防止无限阻塞,又能在满足条件时迅速返回,适用于需要同步操作的场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

提供一种思路,将pjnath非阻塞函数改造为阻塞函数,同样适用其他非阻塞接口。

背景:

开源库有时候提供的接口并不人性化,例如:

pjnath里的pj_ice_strans_create用来创建一个ice,它调用了sess_init_update(用来检测ice的候选candidate的)。

我们知道本机客户端获取的自身candidate一般需要两个以上才能够有效的实现对remote实现negotiationnegotiation成功之后才能进行NAT的数据发送。

其中一个是自己局域网地址信息,另一个是外网的地址信息,前者是实现局域网连接,后者是实现外网NAT的关键。

针对turn类型的server时:

pj_ice_strans_create-》pj_ice_strans_init_ice-》pj_ice_strans_enum_cands

按上面的顺序调用时,获得的candidate只有一个本机地址信息,没有外网地址信息,无法用于NAT negotiatioin。

而我在跟踪时发现是函数是异步所导致的。stun_on_status和turn_on_state是回调函数,收到socket信息后被才调用,因此存在网络延时,不能及时将外网的candidate更新。

stun_on_status中运行到/* Otherwise update the address */ 后面的cand->status = PJ_SUCCESS;对candidate进行了修改。

turn_on_state 的old_state new_state状态改变时会对candidate进行修改,阻塞可选在函数末尾。

我们要做的就是阻塞这两个位置进行标志变量修改为1,意思是外网candidate已更新。

static void turn_on_state(pj_turn_sock *turn_sock, pj_turn_state_t old_state,  pj_turn_state_t new_state)

ice_strans.c的前边加入

static char stun_cand_update;
static char turn_cand_update;
#define BLOCK_MS_COUNT 8000//stun协议默认7秒

在stun_on_status中

      /* Otherwise update the address */
      pj_sockaddr_cp(&cand->addr, &info.mapped_addr);
      cand->status = PJ_SUCCESS;

后面加入

	stun_cand_update = 1;


于是在此turn_on_state函数最后加入

if (old_state == PJ_TURN_STATE_ALLOCATING && new_state == PJ_TURN_STATE_READY)
{
	turn_cand_update = 1;
}
	

在pj_ice_strans_create末尾部分改为

stun_cand_update = 0;
	turn_cand_update = 0;
	while(stun_cand_update == 0 && turn_cand_update == 0 && ++cnt < BLOCK_MS_COUNT)
	{
		pj_thread_sleep(1);
	}
    /* Check if all candidates are ready (this may call callback) */
    sess_init_update(ice_st);

    pj_log_pop_indent();
	if(stun_cand_update == 1 || turn_cand_update == 1)
	{
		stun_cand_update = stun_cand_update ? 0 : 1;
		turn_cand_update = turn_cand_update ? 0 : 1;
		return PJ_SUCCESS;
	}
	return PJ_FALSE;

 

原理很简单,就是用循环sleep1毫秒来阻塞sess_init_update的执行,使它在turn_on_state获取外网candidate之后才执行。

同步阻塞超时模式的好处:1、不会永远阻塞 2、满足条件时会立即返回,不影响效率。只提供一种思路,要注意多线程等情况,具体情况要具体改动。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值