准备做一个服务器,用5060端口接收客户端的SIP指令,
用28880端口接收客户端的语音包,转发给网关;
接受语音包有异常,
数据包长度都是1,但是通过SNIFFER抓包显示长度是172;请大家分析下面代码,谢谢
//////////////////////////////////////////////////////////////////////////////////////
//接收SIP指令的主要代码
SOCKET mSckSender = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrClent;
memset((char *) &addrClent, 0, sizeof(addrClent));
addrClent.sin_family = AF_INET;
addrClent.sin_addr.s_addr = htonl(INADDR_ANY);
addrClent.sin_port = htons(5060); //接收客户端和网关SIP指令的端口号
int ret = bind(mSckSender, (struct sockaddr*) &addrClent, sizeof(addrClent)); char RecevMsg[1024];
SOCKADDR_IN addrCli;
int addr_cli_len = sizeof(addrCli);
recvfrom(mSckSender, (char *)RecevMsg, 1024, 0,(LPSOCKADDR) &addrCli, (int *) &addr_cli_len);
CString rcvMsg = RecevMsg; //////////////////////////////////////////////////////////////////////////////////////
//接收PC客户端语音包的主要代码
BOOL CSipServerManager::InitSocket(SOCKET &sck,int iPort)
{
sck = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addr;
memset((char *) &addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(iPort); //28880端口用来接收客户端的语音包
int ret = bind(sck, (struct sockaddr*) &addr, sizeof(addr));
return TRUE;
}BOOL CSipServerManager::SendTo(SOCKET sck,const char * inBuffer,DWORD strIP,int iPort)
{
if (sck != INVALID_SOCKET)
{
SOCKADDR_IN addr;
memset((char *) &addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(strIP); //目标IP
addr.sin_port = htons(iPort); //目标端口
//向客户端或网关发消息
int val = sendto(sck, inBuffer, strlen(inBuffer), 0, (sockaddr *) &addr, sizeof(addr));
return (val != SOCKET_ERROR);
}
return FALSE;
}void CSipServerManager::Process_Thread(void)
{
char bytes[1024];
SOCKET udpSckClientToProxy; while (TRUE)
{
InitSocket(udpSckClientToProxy,28880); //28880端口接收客户端的语音包 //接受客户端数据包
recvfrom(udpSckClientToProxy, bytes, 1024, 0,(LPSOCKADDR) &udpAddrHole, (int *) &ilength);
CString strIP=inet_ntoa(udpAddrHole.sin_addr); //PC客户端的IP if (strcmp(strIP,"211.1.1.1") != 0) //收到客户端语音包,转发给网关
{
DWORD dwIP=ntohl(inet_addr("211.1.1.1")); //网关IP
BOOL ret = FALSE;
tmp.Empty();
tmp= bytes; //接收到语音包长度一直为1,通过SNIFFER抓包长度基本都是172
if (tmp.GetLength() >10)
{
//把语音包转发给网关
ret = SendTo(udpSckProxyToGaty,bytes,dwIP,iProxyToGatyPort);
}
}
}
}
用28880端口接收客户端的语音包,转发给网关;
接受语音包有异常,
数据包长度都是1,但是通过SNIFFER抓包显示长度是172;请大家分析下面代码,谢谢
//////////////////////////////////////////////////////////////////////////////////////
//接收SIP指令的主要代码
SOCKET mSckSender = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addrClent;
memset((char *) &addrClent, 0, sizeof(addrClent));
addrClent.sin_family = AF_INET;
addrClent.sin_addr.s_addr = htonl(INADDR_ANY);
addrClent.sin_port = htons(5060); //接收客户端和网关SIP指令的端口号
int ret = bind(mSckSender, (struct sockaddr*) &addrClent, sizeof(addrClent)); char RecevMsg[1024];
SOCKADDR_IN addrCli;
int addr_cli_len = sizeof(addrCli);
recvfrom(mSckSender, (char *)RecevMsg, 1024, 0,(LPSOCKADDR) &addrCli, (int *) &addr_cli_len);
CString rcvMsg = RecevMsg; //////////////////////////////////////////////////////////////////////////////////////
//接收PC客户端语音包的主要代码
BOOL CSipServerManager::InitSocket(SOCKET &sck,int iPort)
{
sck = socket(AF_INET, SOCK_DGRAM, 0);
SOCKADDR_IN addr;
memset((char *) &addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(iPort); //28880端口用来接收客户端的语音包
int ret = bind(sck, (struct sockaddr*) &addr, sizeof(addr));
return TRUE;
}BOOL CSipServerManager::SendTo(SOCKET sck,const char * inBuffer,DWORD strIP,int iPort)
{
if (sck != INVALID_SOCKET)
{
SOCKADDR_IN addr;
memset((char *) &addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(strIP); //目标IP
addr.sin_port = htons(iPort); //目标端口
//向客户端或网关发消息
int val = sendto(sck, inBuffer, strlen(inBuffer), 0, (sockaddr *) &addr, sizeof(addr));
return (val != SOCKET_ERROR);
}
return FALSE;
}void CSipServerManager::Process_Thread(void)
{
char bytes[1024];
SOCKET udpSckClientToProxy; while (TRUE)
{
InitSocket(udpSckClientToProxy,28880); //28880端口接收客户端的语音包 //接受客户端数据包
recvfrom(udpSckClientToProxy, bytes, 1024, 0,(LPSOCKADDR) &udpAddrHole, (int *) &ilength);
CString strIP=inet_ntoa(udpAddrHole.sin_addr); //PC客户端的IP if (strcmp(strIP,"211.1.1.1") != 0) //收到客户端语音包,转发给网关
{
DWORD dwIP=ntohl(inet_addr("211.1.1.1")); //网关IP
BOOL ret = FALSE;
tmp.Empty();
tmp= bytes; //接收到语音包长度一直为1,通过SNIFFER抓包长度基本都是172
if (tmp.GetLength() >10)
{
//把语音包转发给网关
ret = SendTo(udpSckProxyToGaty,bytes,dwIP,iProxyToGatyPort);
}
}
}
}
int msgLen =
recvfrom(udpSckClientToProxy, bytes, 1024, 0,(LPSOCKADDR) &udpAddrHole, (int *) &ilength);
CString strMsg = bytes;//把语音包转发给网关
ret = SendTo(udpSckProxyToGaty,bytes,dwIP,iProxyToGatyPort); msgLen返回值是172,但是strMsg长度为1,
使用SNIFFER抓包显示,发送给网关的数据包长度一直为1
//接受客户端数据包
recvfrom(udpSckClientToProxy, bytes, 1024, 0,(LPSOCKADDR) &udpAddrHole, (int *) &ilength);
int nReceivedLen = recvfrom(....);看一下长接收到的长度.
DWORD g_threadID;#ifdef FD_SETSIZE
#undef FD_SETSIZE
#define FD_SETSIZE 1024
#endifDWORD WINAPI PhoneServices(LPVOID param)
{
hostent *hostAddr;
char hostName[256]={0};
gethostname(hostName,256);
hostAddr=gethostbyname(hostName);
char *IP;
IP=inet_ntoa(*((struct in_addr*)hostAddr->h_addr_list[0]));
CManagerClient manager; SOCKET sock_Server=socket(AF_INET,SOCK_DGRAM,0);
sockaddr_in ser_Addr={0};
ser_Addr.sin_addr.s_addr=inet_addr(IP);
ser_Addr.sin_family = AF_INET;
ser_Addr.sin_port = htons(g_ser_info.GetSerPort()); //配置文件中获得
int addr_Len = sizeof(sockaddr_in);
bind(sock_Server,(sockaddr*)&ser_Addr,addr_Len);
if(WSAGetLastError()!=0)
{
AfxMessageBox("服务器开启失败:已开启或端口占用!");
}
while(1)
{
fd_set serv_Set;
FD_ZERO(&serv_Set);
FD_SET(sock_Server,&serv_Set);
timeval time_Out={g_ser_info.GetTimeOut(),0}; //配置文件中获得
int res=select(0,&serv_Set,NULL,NULL,&time_Out);
if(res==0 || res==-1)
{
TRACE("timeout or error:%d\n",res);
}
else if(FD_ISSET(sock_Server,&serv_Set))
{
char buf[1024]={0};
sockaddr_in client_Addr={0};
recvfrom(sock_Server,buf,1024,0,(sockaddr*)&client_Addr,&addr_Len);
manager.MessageSwitch(sock_Server,buf,client_Addr);
} Sleep(100);
MSG msg_Stop;
if(PeekMessage(&msg_Stop,NULL,0,0,0))
{
GetMessage(&msg_Stop,NULL,0,0);
if(msg_Stop.message==WM_THREAD_STOP)
{
break;
}
}
}
closesocket(sock_Server);
return 0;
}
客户端和网关协商,
支持的音频格式,pt=0(g711.u),pt=101 网关异常日志:
10d:17h:51m:3s (lgr_coders_list)(5696 )
?? [WARNING] ACCodersList::IsMatch found match with different intervals g711Ulaw64k10 (10 != 20) #ifdef FD_SETSIZE
#undef FD_SETSIZE
#define FD_SETSIZE 1024
#endif fd_set serv_Set;
FD_ZERO(&serv_Set);
FD_SET(udpSckClientToProxy,&serv_Set);
timeval time_Out={20,0}; //设置接收数据的超时时间200ms
int res=select(0,&serv_Set,NULL,NULL,&time_Out); if(res==0 || res==-1)
{
TRACE("timeout or error:%d\n",res);
}
else if(FD_ISSET(udpSckClientToProxy,&serv_Set))
{
char buf[1024]={0};
bRsLength=recvfrom(udpSckClientToProxy,buf,1024,0,(sockaddr*)&udpAddrHole,&ilength);
CString strIP=inet_ntoa(udpAddrHole.sin_addr); //客户端或网关的IP //把语音包转发给网关
}
bRsLength=recvfrom(udpSckClientToProxy,buf,1024,0,(sockaddr*)&udpAddrHole,&ilength); tmp.Empty();
tmp= buf;
int k = tmp.GetLength(); bRsLength的值为172,但是k的值为1,很奇怪
把
tmp.Empty();
tmp = buf;
替换为:
tmp.Format(_T("%s"),buf);
不是字符串的对象赋值到了CSTRING,只会截取到0X00前的部分。
CString str;感觉str=buf;没有问题,之前这样传过值...
tmp.Empty();
tmp = buf;
替换为:
tmp.Format(_T("%s"),buf);还是有问题,buf长度为172(recvfrom返回值),
tmp长度还是1
还有下面的超时时间,是否有影响呢?
#ifdef FD_SETSIZE
#undef FD_SETSIZE
#define FD_SETSIZE 1024
#endif fd_set serv_Set;
FD_ZERO(&serv_Set);
FD_SET(udpSckClientToProxy,&serv_Set);
timeval time_Out={20,0}; //设置接收数据的超时时间200ms
int res=select(0,&serv_Set,NULL,NULL,&time_Out);
Format不是一样的?你还是没明白。
你这样,在你的recvfrom后加一句,打印出来贴上了for (int i = 0; i < bRsLength; i++)
{
if (i % 16)
TRACE("\n");
TRACE("%02X ", buf[i]);
}
{
if (i % 16)
TRACE("\n");
TRACE("%02X ", buf[i]);
}下面是输出结果...
FFFFFF80
FFFFFF80
FFFFFFB6
FFFFFFD6
FFFFFFBC
03
51
06
1A
FFFFFFC5
7E
1D
7A
7D
7A
78 77
74
73
6F
71
71
73
74
73
72
72
70
6E
6D
6E
72 76
79
7F
FFFFFFFC
FFFFFFF6
FFFFFFF5
FFFFFFF1
FFFFFFEE
FFFFFFED
FFFFFFEE
FFFFFFEE
FFFFFFEE
FFFFFFED
FFFFFFED
FFFFFFEE
FFFFFFEE FFFFFFEF
FFFFFFEF
FFFFFFEF
FFFFFFF0
FFFFFFF1
FFFFFFF1
FFFFFFF1
FFFFFFF5
FFFFFFF8
FFFFFFFB
FFFFFFFC
FFFFFFFD
FFFFFFFF
7F
FFFFFFFF
FFFFFFFF 7E
7D
7E
FFFFFFFF
FFFFFFFE
7E
7E
7B
7A
7A
7B
7C
7D
7E
7F
FFFFFFFE FFFFFFFC
FFFFFFF9
FFFFFFF5
FFFFFFEF
FFFFFFEC
FFFFFFEB
FFFFFFE8
FFFFFFE7
FFFFFFE6
FFFFFFE5
FFFFFFE4
FFFFFFE3
FFFFFFE3
FFFFFFE4
FFFFFFE4
FFFFFFE4 FFFFFFE6
FFFFFFE7
FFFFFFEA
FFFFFFEA
FFFFFFEE
FFFFFFEF
FFFFFFF3
FFFFFFFA
FFFFFFFB
FFFFFFF9
FFFFFFF9
FFFFFFFA
FFFFFFFA
FFFFFFFC
FFFFFFFB
FFFFFFFC FFFFFFFB
FFFFFFFB
FFFFFFF8
FFFFFFF4
FFFFFFEF
FFFFFFED
FFFFFFE8
FFFFFFE5
FFFFFFE1
FFFFFFDF
FFFFFFDE
FFFFFFDE
FFFFFFDE
FFFFFFDF
FFFFFFDF
FFFFFFE1 FFFFFFE1
FFFFFFE4
FFFFFFE7
FFFFFFE8
FFFFFFE9
FFFFFFEC
FFFFFFED
FFFFFFF0
FFFFFFF7
FFFFFFFA
FFFFFFFD
7F
FFFFFFFF
FFFFFFFF
FFFFFFFD
FFFFFFFC FFFFFFFD
FFFFFFFD
FFFFFFFD
FFFFFFFF
7E
7D
7C
7C
79
7A
79
78
77
78
7B
7D 7D
FFFFFFFF
FFFFFFFF
FFFFFFFD
FFFFFFFD
FFFFFFF7
FFFFFFF6
FFFFFFF4
FFFFFFF0
FFFFFFEE
FFFFFFED
FFFFFFED
buf中显示的值如下:
+ buf 0x0123ed18 "€€吨?Q舿z}zxwtsoqqstsrrpnmnrvy躐铐铑铐眍铒镲瘃耨貘?~}~~{zz{|}~镬腓珂邃沣滗滏珀觐矬麸龛遽咿揶哌後溏栝祉瘅?~}||yzyxwx{}}黯麴铐
你的数据一直是这样的吗?我能够GetLength()到不为1
后面都是只收到一个字符:
+ buf 0x012bed14 "€"
- tmp {"€"}
FFFFFF80
FFFFFF80
7C
1A
2D
FFFFFFA1
FFFFFFFB
FFFFFFAB
FFFFFFA6
FFFFFFB2
FFFFFF8D
28
6D
6F
76
79 7B
7E
7F
7B
7C
7C
FFFFFFFF
7E
7C
78
77
72
6F
6E
6E
6C 6C
6D
6E
6C
6A
6A
6A
69
69
68
68
66
68
6A
6A
6B 6C
6D
6B
6A
6B
6C
6D
6D
6F
6F
6F
6E
6F
6E
6D
6E 71
74
73
71
72
74
76
73
6E
6C
69
68
67
66
65
66 65
64
64
63
64
66
67
67
67
69
69
6B
6D
6E
6E
6F 72
75
75
77
7C
FFFFFFFC
FFFFFFFC
FFFFFFFC
FFFFFFFE
7D
7A
77
75
73
6E
6B 6B
6A
6A
68
66
67
68
69
68
68
6A
6C
6D
6F
70
73 77
7A
7B
76
74
75
75
76
73
75
79
78
73
6E
6D
6A 68
67
67
68
67
67
68
6B
6B
6A
68
65
63
61
61
61 60
61
5F
61
62
63
63
63
63
64
66
67
23楼的是你GetLength()为1的buf数据?
一个线程处理SIP指令(thrd111,sock111,SIP指令的端口5060),
一个线程处理音频数据包(thrd222,sock222,接收语音包的端口28880);是不是这两个线程序相互干扰造成的?
把temp.Empty()这行去掉.我之前也是用了这行,一直没收到过数据.
给你一段我的UDP接收程序参考一下:BOOL CUDPDlg::InitSock()
{
BOOL result = true;
CString strTemp = "";
SOCKET m_hSock = socket(AF_INET,SOCK_DGRAM,IPPROTO_IP);
if(m_hSock == INVALID_SOCKET)
{
strTemp.Format("Initialize socket library error!\r\nError code:%d",WSAGetLastError());
AfxMessageBox(strTemp);
return false;
} UpdateData();
SOCKADDR_IN addrSock;
addrSock.sin_family = AF_INET;
addrSock.sin_addr.S_un.S_addr = INADDR_ANY;
addrSock.sin_port = htons(m_localport);
BOOL bDontLinger = true;
setsockopt(m_hSock,SOL_SOCKET,SO_REUSEADDR,(char *)&bDontLinger,sizeof(BOOL));
if(bind(m_hSock,(SOCKADDR *)&addrSock,sizeof(SOCKADDR)) == SOCKET_ERROR)
{
strTemp.Format("Bind socket error!\r\nError code:%d",WSAGetLastError());
AfxMessageBox(strTemp);
return false;
} int rc = WSAAsyncSelect(m_hSock,m_hWnd,WM_SOCK_RECV,FD_READ);
if(rc == SOCKET_ERROR)
{
closesocket(m_hSock);
strTemp.Format("Listen socket error!\r\nError code:%d",WSAGetLastError());
AfxMessageBox(strTemp);
return false;
} return result;
}void CUDPDlg::OnRecv(WPARAM wParam,LPARAM lParam)
{
SOCKET hSock = (SOCKET)wParam;
SOCKADDR_IN clintSock;
int sockLen = sizeof(SOCKADDR_IN);
char buff[255] = "";
CString strTemp = "";
UpdateData();
switch(LOWORD(lParam))
{
case FD_READ:
recvfrom(hSock,buff,255,0,(SOCKADDR *)&clintSock,&sockLen);
strTemp.Format("%s:%d>\r\n\t%s\r\n",inet_ntoa(clintSock.sin_addr),clintSock.sin_port,buff);
m_recvtext += strTemp;
UpdateData(false);
break;
}
}
你的数据的第二个字节不是0X00,我把你的数据从前摘取了10个,能够成功赋值给CSTRING
这个函数要放回掉函数里么?
我用的是WSAAsyncSelect模型BEGIN_MESSAGE_MAP(CUDPDlg, CDialog)
//{{AFX_MSG_MAP(CUDPDlg)
ON_WM_SYSCOMMAND()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDC_BUTTON_CONNECT, OnButtonConnect)
ON_BN_CLICKED(IDC_BUTTON_SEND, OnButtonSend)
//}}AFX_MSG_MAP
ON_MESSAGE(WM_SOCK_RECV,OnRecv) //接收消息
END_MESSAGE_MAP()
在send(),recv()过程中有时由于网络状况等原因,发收不能预期进行,而设置收发时限:
int nNetTimeout=1000;//1秒
//发送时限
setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
//接收时限
setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));
//发送和接受的数据不一定是字码
//接受数据的长度是recvfrom函数的返回值,不要把数据赋值给字符串,在赋值过程中会丢失数据,直接用接受的char *发送即可
发送代码改为如下:
BOOL CSipServerManager::SendTo(SOCKET sck,const char * inBuffer,int len,DWORD strIP,int iPort)
{
if (sck != INVALID_SOCKET)
{
SOCKADDR_IN addr;
memset((char *) &addr, 0, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(strIP); //目标IP
addr.sin_port = htons(iPort); //目标端口//向客户端或网关发消息
int val = sendto(sck, inBuffer, len, 0, (sockaddr *) &addr, sizeof(addr));
return (val != SOCKET_ERROR);
}
return FALSE;
}