itclockcn;
  你说的没错,我是在学生端,既广播的接收端出现10040错误的.为什么会出现这样的错误?我在学生端已经指定了接受的最大字节数了啊.
  是不是过来的数据包,除了头部之外还有一部分音频数据在里面?因为第一次recvfrom只接收头部,所以出现错误.
  但是这种情况在非广播的情况下不会出现啊,我使用tcp,可以接收.

解决方案 »

  1.   

    这和你的发送端速率有关系。我做过接收组播的mp3的程序,mp3的速率一般在100多k/s,我定义的缓冲区较小时就会出现这种问题。TCP是流式的,所以不会有问题。而UDP是数据报,一次接收要把整个报文都收下来,因此缓冲区一定要够大。
      

  2.   

    好的!
    xuying等一下,我这就贴出来;)
      

  3.   

    消息处理;
    case UM_SOCK:
    switch (lParam)
    {

    case FD_READ:memset(&m_vtRecvMsgBuf,0,SIZEVTMSGHDR);
    RecvVTMessage(sock_student,&m_vtRecvMsgBuf);
    // Parse the message and display it
    ParseMsgData();
    TextOut(GetDC(hWnd),23+j++,34,"accept",6);
    replay=1;

    break;
    case FD_WRITE:
    if (!SetSelect(sock_student,hWnd,FD_READ))
    return (FALSE);
    break;
    case FD_CLOSE:
    break;
    default:
    break;
                }
    break;
      

  4.   

    BOOL RecvVTMessage(SOCKET Sock, LPVTMSG recvBuf)
    {
        int byteLeft; 
    int byteAll;
    int msgSize;
    int byteRead;
    LPVTMSG pData = new VTMSG;
    memset((void*)pData, 0, VT_MAX);
        
         byteLeft = SIZEVTMSGHDR;    // First time to read message to determine the message type information 
    // and size data
    int nSize=sizeof(SOCKADDR_IN);
    if((byteAll=recvfrom(Sock,(char *)pData,byteLeft,0,
    (SOCKADDR FAR*)&saClient,&nSize))==SOCKET_ERROR)
    { //char buff[10];
    //sprintf(buff,"%ld",GetLastError());
    //MessageBox(NULL,buff,"sys",MB_OK);
    return 0;
    }    // Check the message identity to make sure it is valid message
        if(pData->m_ucIdentity != VT_IDENTITY)
        {
            //Wrong message
            return FALSE;
        }    msgSize = pData->m_lLength;  // The total size of the message
        byteLeft = msgSize - byteAll;  // The bytes left to read    while(byteAll < msgSize)
        {
            // Read the message from the stream sockets
    if((byteAll=recvfrom(Sock,
    (char *)pData+byteAll,
    byteLeft,
    0,
    SOCKADDR FAR*)&saClient,
    &nSize))==SOCKET_ERROR)
            {
                if ((int)WSAGetLastError() != WSAEWOULDBLOCK)
                {
                    // ERROR
                    return FALSE;
                }
            }
            byteAll += byteRead;
            byteLeft -= byteRead;
        } memcpy((void*)recvBuf, (void*)pData, SIZEVTMSG); delete []pData;    return TRUE;
    }
      

  5.   

    以上改自,tcp连接程序,无法实现网络广播的接收.
    VTMSG是网络音频数据包结构
      

  6.   

    有几处疑问:
    1. VTMSG有多大空间? 即VT_MAX是多少?
    LPVTMSG pData = new VTMSG;
    memset((void*)pData, 0, VT_MAX)2. 是第一次接收出错,还是第二次?
    if((byteAll=recvfrom(Sock,(char *)pData,byteLeft,0,
    (SOCKADDR FAR*)&saClient,&nSize))==SOCKET_ERROR)
    ;我的看法:
    由于广播中是UDP,所以再发送的时候也应该有两次发送,第一次发大小,第二次发实际数据。
    而你的程序中采用的是TCP的方式,即发送的是数据流,所以用了while循环。
    而如果你的socket是UDP的,只要你sendBuf的大小不超过64k,这个循环只会执行一次,也就是说你的大小和实际数据在一个UDP报文中发送了。而接收端再第一次接收时就全部接收下来,可能造成接收buf不够大。关键在于TCP的方式不能用于UDP方式,你对数据报和流式的传输方式理解上可能有问题。  if((sendingSize = (int)sendto(sock_v_s, (char *)sendBuf + byteSent, 
    byteAll - byteSent, 0,(SOCKADDR *)&broadcast_student,sizeof(SOCKADDR_IN))) == SOCKET_ERROR)
      

  7.   

    嗯;)xuying,你说的不错.出错是出现在第一个recvfrom上!
    昨晚对程序进行了一下修改,就是将BOOL RecvVTMessage()函数中,第一个接收语句,如下:
    if((byteAll=recvfrom(Sock,(char *)pData,byteLeft,0,(SOCKADDR FAR*)&saClient,&nSize))==SOCKET_ERROR)
    改为:
    if((byteAll=recvfrom(Sock,(char *)pData,byteLeft+VT_MAX,0,(SOCKADDR FAR*)&saClient,&nSize))==SOCKET_ERROR)
    :)
    程序运行通过!音频发送,接收播放正常.VTMSG是用户定义的存储音频的数据结构,其中包括格式,数据区的大小.
    VT_MAX是用户定义的VTMSG结构中音频数据区的大小,形式是这样的
    BYTE pdata[VT_MAX].我的理解是:
    我之所以改成byteLeft+VT_MAX,意思是byteLeft(VTMSG结构头部大小,不包括数据区)+VT_MAX(数据区的大小),这样子可以接收发过来的一个完整的数据包.
    这样,第一个recvfrom的接收缓冲区pData在构造的时候被格式化成了VTMSG形式,所以还是可以进行数据的判断:pData->m_ucIdentity != VT_IDENTITY;获取整个数据包的大小pData->m_lLength的.
    至于第二个recvfrom起不起作用,我还没调试,估计不起作用;)
    倒数第四句:memcpy((void*)recvBuf, (void*)pData, SIZEVTMSG);将接收的数据拷贝到了recvBuf中,供播放函数使用!在发送端,我是指定音频数据区甜满即录取VT_MAX的值后,马上广播发送的,所以接收端因该是接收到一个包.xuying给点意见:)