itclockcn;
你说的没错,我是在学生端,既广播的接收端出现10040错误的.为什么会出现这样的错误?我在学生端已经指定了接受的最大字节数了啊.
是不是过来的数据包,除了头部之外还有一部分音频数据在里面?因为第一次recvfrom只接收头部,所以出现错误.
但是这种情况在非广播的情况下不会出现啊,我使用tcp,可以接收.
你说的没错,我是在学生端,既广播的接收端出现10040错误的.为什么会出现这样的错误?我在学生端已经指定了接受的最大字节数了啊.
是不是过来的数据包,除了头部之外还有一部分音频数据在里面?因为第一次recvfrom只接收头部,所以出现错误.
但是这种情况在非广播的情况下不会出现啊,我使用tcp,可以接收.
xuying等一下,我这就贴出来;)
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;
{
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;
}
VTMSG是网络音频数据包结构
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)
昨晚对程序进行了一下修改,就是将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给点意见:)