实现国标GB/T2818视频流媒体解决方案EasyGBS国标GB28181-2016版的sip协议tcp沾包流程说明介绍
程序员文章站
2022-07-05 19:08:15
...
GB/T2818视频流媒体解决方案是基于GB/T28181协议进行模块化设计、支持分布式部署;具有设备管理模块、信令模块、流媒体模块;支持多个中心信令服务器部署、支持多个流媒体负载均衡;流媒体模块支持RTSP、RTMP、FLV、HLS多种协议访问;支持对摄入摄像机的云台控制;完全满足全新建设的数字监控网络和已经部分建设的数字监控兼容部署。
由于GB28181设计的时候基本很少使用tcp包,只有在资源推送和录像检索查询返回的时候才会使用的tcp消息,下面简单说一下tcp消息使用,首先建立一个tcp短连接,然后将消息发送出去,消息长度尽量在2M以下。
下面粘贴一段sip消息tcp沾包的代码,希望对您有所帮助。
void CUvSocketTransMgr::sip_tcp_sticky_packet(TUvSocketItem * pSocketItem, const char *pData, int len, const char *pSrcIP, int SrcPort,const char* pDestIP,int DestPort)
{
if(len > 0)
{
char *end_sip = NULL;
char *cl_header = NULL;
int cl_size = 0;
if(pSocketItem->pTcpRecvData != NULL)
{
/* concat old data with new data */
pSocketItem->pTcpRecvData = (char *)realloc(pSocketItem->pTcpRecvData, pSocketItem->nTcpRecvLen+len+1);
if(NULL == pSocketItem->pTcpRecvData)
{
printf("realloc pTcpRecvData failed!\n");
pSocketItem->nTcpRecvLen = 0;
return;
}
strncpy(pSocketItem->pTcpRecvData+pSocketItem->nTcpRecvLen, pData, len);
pSocketItem->pTcpRecvData[pSocketItem->nTcpRecvLen+len] = '\0';
pSocketItem->nTcpRecvLen = pSocketItem->nTcpRecvLen + len;
}
if(NULL == pSocketItem->pTcpRecvData)
{
pSocketItem->pTcpRecvData = (char *)malloc(len+1);
if(pSocketItem->pTcpRecvData != NULL)
{
memset(pSocketItem->pTcpRecvData, 0, len+1);
}
strncpy(pSocketItem->pTcpRecvData, pData, len);
pSocketItem->pTcpRecvData[len] = '\0';
pSocketItem->nTcpRecvLen = len;
}
end_sip = strstr(pSocketItem->pTcpRecvData, "\r\n\r\n");
while(end_sip != NULL)
{
cl_header = mystrcasestr(pSocketItem->pTcpRecvData, "\ncontent-length ");
if (cl_header == NULL || cl_header > end_sip)
cl_header = mystrcasestr(pSocketItem->pTcpRecvData,"\ncontent-length:");
if (cl_header == NULL || cl_header > end_sip)
cl_header =mystrcasestr(pSocketItem->pTcpRecvData,"\r\nl ");
if (cl_header == NULL || cl_header > end_sip)
cl_header =mystrcasestr(pSocketItem->pTcpRecvData,"\r\nl:");
if (cl_header != NULL && cl_header < end_sip)
cl_header = strchr(cl_header, ':');
if (cl_header == NULL || cl_header >= end_sip)
{
/* remove data up to crlfcrlf and restart */
memmove(pSocketItem->pTcpRecvData, end_sip+4,pSocketItem->nTcpRecvLen -(end_sip + 4 -pSocketItem->pTcpRecvData) + 1);
pSocketItem->nTcpRecvLen = pSocketItem->nTcpRecvLen - (end_sip +4 -pSocketItem->pTcpRecvData);
pSocketItem->pTcpRecvData = (char *)realloc(pSocketItem->pTcpRecvData, pSocketItem->nTcpRecvLen+1);
if(pSocketItem->pTcpRecvData == NULL)
{
pSocketItem->nTcpRecvLen = 0;
break;
}
end_sip =strstr(pSocketItem->pTcpRecvData,"\r\n\r\n");
continue; /* and restart from new CRLFCRLF */
}
/* header content-length was found before CRLFCRLF -> all headers are available */
cl_header++; /* after ':' char */
cl_size = atoi(cl_header);
if (cl_size == 0|| (cl_size >0 && (end_sip + 4 + cl_size <=pSocketItem->pTcpRecvData+pSocketItem->nTcpRecvLen)))
{
uv_mutex_lock(&mutex_data_);
RecvPacketCallBack(pSocketItem->socketfd,pSocketItem->pTcpRecvData, (end_sip + 4 + cl_size -pSocketItem->pTcpRecvData),\
pSrcIP,SrcPort,pDestIP,DestPort, true);
uv_mutex_unlock(&mutex_data_);
if (pSocketItem->nTcpRecvLen -(end_sip + 4 + cl_size -pSocketItem->pTcpRecvData) == 0)
{
end_sip = NULL;
pSocketItem->nTcpRecvLen = 0;
free(pSocketItem->pTcpRecvData);
pSocketItem->pTcpRecvData = NULL;
continue;
}
memmove(pSocketItem->pTcpRecvData,end_sip + 4 + cl_size, pSocketItem->nTcpRecvLen -(end_sip + 4 + cl_size -pSocketItem->pTcpRecvData) + 1);
pSocketItem->nTcpRecvLen = pSocketItem->nTcpRecvLen - (end_sip +4 +cl_size -pSocketItem->pTcpRecvData);
pSocketItem->pTcpRecvData = (char *)realloc(pSocketItem->pTcpRecvData,pSocketItem->nTcpRecvLen + 1);
if (pSocketItem->pTcpRecvData == NULL)
{
printf("realloc pSocketItem->pTcpRecvDatapSocketItem->pTcpRecvDatapSocketItem->pTcpRecvData!!\n");
pSocketItem->nTcpRecvLen = 0;
break;
}
end_sip =strstr(pSocketItem->pTcpRecvData,"\r\n\r\n");
continue; /* and restart from new CRLFCRLF */
}
/* uncomplete SIP message */
end_sip = NULL;
}
if (pSocketItem->nTcpRecvLen== 0)
{
/* all data consumed are reallocation error ? */
return;
}
}
else if(len< 0)
{
printf("Could not read socket (%d)- close it\n",pSocketItem->socketfd);
//DelSocketItem(pSocketItem);
//close(pSocketItem->sock);
}
else if (len == 0)
{
printf("End of stream (read 0 byte from %s:%i)\n", pSocketItem->srcip, pSocketItem->srcport);
//DelSocketItem(pSocketItem);
//close(pSocketItem->sock);
}
else
{
printf("Dummy SIP message received (size=%d)\n", len);
}
}
GB/T28181视频流媒体解决方案播放效果可见下图: