最近在调试NVR的GB28181接入功能时,遇到了UDP收流recvfrom一直返回0的问题。奇怪的是天地的ipc是正常的可以收到数据和预览,而自研ipc有问题,收不到数据,而且是概现的,概率很高。
具体情况是:
SIP使用invite发起流会话,使用UDP方式,与IPC的信令交互正常,NVR返回ACK后,NVR建立UDP收流端口,IPC开始发流。在NVR端循环调用recvfrom函数读数据的时候,一直返回0,读不到数据,导致超时,NVR关闭的流会话。
定位:
通过抓包,发现流程有问题:nvr在收到ipc的sdp信息后,在还没有完成收流端口初始化(打开端口)直接就返回了ack,这时ipc开始发流,由于nvr还没有打开端口,就报了icmp的端口不可达消息给ipc,ipc检测到端口不可达错误报文就停止了发流。而nvr初始化好端口后持续调用recvfrom接收数据,就一直返回0。
对天地ipc也进行了抓包,发现它忽略了icmp端口不可达消息,持续发送数据,这也解释了为什么自研ipc不能预览而天地的可以。
关于概现:ipc收到ack后开始发送数据的时间间隔就是不固定的,因为帧率25的情况下,每40ms发一帧数据,而收到ack的时间是随机的,所以从收到ack开始到开始发送数据的时间间隔应该是0-40ms之间的随机值,当间隔时间比较长(实测大于35ms)时,自研ipc也能预览,因为这时候nvr端口已准备好了,当时间间隔比较小时,不能预览,因为nvr端口还没有准备好,返回端口不可达icmp,导致ipc不发送数据了。
解决:
修改invite流程,修改成nvr初始化完成收流端口后再应答ack给ipc。实测问题得到解决。