TCP接受连续大数据流

最近做的一个视频数据传输项目,发现密集型的数据发送,在接收端如果仅仅只是先接收固定长度的包头数据,按照包头数据的内容,获取后续数据的长度,再进行接收,这样做在本机上运行或许没有什么问题,一旦到了网络上就不行了。可能会出现错包的情况,也就是说,你认为你接收的是包头数据,但那不是真正的包头数据,因此,你对后续数据的接收就完全错位了。解决这个办法要加强对包头数据的检测,并且要在接收的过程中进行分包和并包的处理,也就是说把多余的数据缓存下来,和下一次接收的数据进行合并

    int nRecvLen=0;
   
    //接收数据
    nRecvLen=recv(m_nFileSocket, chTempBuffer+m_nRecvSize, MAX_TEMP_BUFFER - m_nRecvSize, 0);
    if( nRecvLen == SOCKET_ERROR )
    {
        return;
    }

    if(nRecvLen>0)
    {
        m_nRecvSize+=nRecvLen;
       
        TRACE("recv buffer size %d /n",nRecvLen);
    }
   
//    TRACE("recv buffer size %d /n",m_nRecvSize);

    //分包
    int nIndex=0;
    int nHeadPos=0;
    int nHeadPosNow=0;
    while((nHeadPos=SearchHeadPos(chTempBuffer+nIndex,m_nRecvSize-nIndex))>=0)  //找到合适的包头数据
    {
        if(nHeadPos!=0)
        {
            nHeadPosNow=nHeadPos;
        }

        TRACE("HEAD POS %d /n",nHeadPos);
        TLVSTREAMINFO* pStreamInfo=(TLVSTREAMINFO*)(chTempBuffer+nIndex+nHeadPos);
        if( m_nRecvSize-nIndex-nHeadPos > pStreamInfo->udwBuffSize )   //是一个完整的数据包
        {
            /*
            *    将数据先缓存起来,到达一定数值以后,再进行播放
            */
                   
            if( (MAX_VIDEO_BUFFER-m_nBufferIndex)> pStreamInfo->udwBuffSize + sizeof(TLVSTREAMINFO))
            {
                //缓冲空间可以容纳新的数据包
                memcpy(m_chVideoBuffer+m_nBufferIndex,chTempBuffer+nIndex+nHeadPos,pStreamInfo->udwBuffSize + sizeof(TLVSTREAMINFO));
                       
                TLVSTREAMTag* streamTag=new TLVSTREAMTag;
                streamTag->dwTimeTag=pStreamInfo->dwTimeTag;
                streamTag->dwMillisTag=pStreamInfo->dwMillisTag;
                streamTag->udwDataSize=pStreamInfo->udwBuffSize + sizeof(TLVSTREAMINFO);
                streamTag->ucwIndexPos=m_nBufferIndex;

                StreamList.push_back(streamTag);

                //更新m_nBufferIndex的大小
                m_nBufferIndex+=pStreamInfo->udwBuffSize + sizeof(TLVSTREAMINFO);   
            }               
            else
            {
                if( pStreamInfo->udwBuffSize > MAX_VIDEO_BUFFER || pStreamInfo->udwBuffSize < 0 )
                {
                    return;
                }

                //缓冲空间不可以容纳新的数据包,再从头部开始缓存数据
                m_nBufferIndex=0;
                memcpy(m_chVideoBuffer+m_nBufferIndex,chTempBuffer+nIndex+nHeadPos,pStreamInfo->udwBuffSize + sizeof(TLVSTREAMINFO));
                       
                TLVSTREAMTag* streamTag=new TLVSTREAMTag;
                streamTag->dwTimeTag=pStreamInfo->dwTimeTag;
                streamTag->dwMillisTag=pStreamInfo->dwMillisTag;
                streamTag->udwDataSize=pStreamInfo->udwBuffSize + sizeof(TLVSTREAMINFO);
                streamTag->ucwIndexPos=m_nBufferIndex;
                       
                StreamList.push_back(streamTag);
                       
                //更新m_nBufferIndex的大小
                m_nBufferIndex+=pStreamInfo->udwBuffSize + sizeof(TLVSTREAMINFO);
            }

            nIndex+=pStreamInfo->udwBuffSize + sizeof(TLVSTREAMINFO);
           
            m_nRecvCount++;

//            TRACE("recv buffer number %d /n",m_nRecvCount);

            //启动播放
            if(m_nRecvCount>100)
            {
                if(!m_bTimerInit)
                {
                    if(StreamList.size()>0)
                    {
                        TLVSTREAMTag* streamTag=StreamList.front();
                        if(streamTag)
                        {
                            //记录此帧的相关时间信息
                            m_StreamInfo.dwTimeTag=streamTag->dwTimeTag;
                            m_StreamInfo.dwMillisTag=streamTag->dwMillisTag;
                           
                            //记录此帧的旧的us
                            lMilliSecondOld=streamTag->dwMillisTag;
                           
                            //记录此帧的旧的ACE_TimeVal,便于相减计算时间间隔
                            time_old.tv_sec=streamTag->dwTimeTag;
                            time_old.tv_usec=streamTag->dwMillisTag;
                           
                            //发送第一帧数据
                            m_pFilePlay->VideoPlayDataCome(m_nWnd,(char*)(m_chVideoBuffer+streamTag->ucwIndexPos+sizeof(TLVSTREAMINFO)),streamTag->udwDataSize-sizeof(TLVSTREAMINFO));
                            //设置初始的时间间隔40ms
                            m_Timer=timeSetEvent(40, 1,
                                (LPTIMECALLBACK) OneMilliSecondTimer,
                                (DWORD)this,TIME_PERIODIC);
                           
                           
                            //更新数据
                            StreamList.pop_front();
                            delete streamTag;
                           
                            m_bTimerInit=true;
                        }
                    }
                   
                }
            }
        }
        else
        {
            TRACE("HEAD POS %d /n",nHeadPos);
            nHeadPos=0;
            break;
        }
    }

    if(nIndex>0)
    {
        if( nIndex + nHeadPosNow < m_nRecvSize)
        {
            //有数据全部没有处理完毕,将数据移动到缓冲区头部
            memcpy(chTempBuffer,chTempBuffer+nIndex+nHeadPosNow,m_nRecvSize-nIndex-nHeadPosNow);
            m_nRecvSize=m_nRecvSize-nIndex-nHeadPosNow;  //更新位置

            if(chTempBuffer[0]!='N' && chTempBuffer[1]!='J' && chTempBuffer[2]!='D' && chTempBuffer[3]!='V')
            {
                int nnnnn=0;

            }
        }
        else
        {
            m_nRecvSize=0;
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值