1.需求
判断IP为172.16.0.64 端口为6754的服务器在2秒内有没有向IP为172.16.0.140 端口为6754的客户端发出UDP广播包消息。
2.UDP通信步骤
1.创建套接字Socket对象
2.setsockopt()设置超时
3.创造SOCKADDR_IN对象
4.bind()绑定
5.recv()接收消息
3.问题
采用网上的代码和其他项目的代码,均无法实现UDP通信。
4.原因
发现C++标准库functional.h中存在和WinSock2.h中同名的bind()函数,程序默认使用标准库,导致绑定失败。
5.解决办法
在bind()前加::以区分命名空间。
6.源代码
SOCKET UDPSck;
BOOL SOCKET_UDP_Init(SOCKET* sock)
{
int Port = 6754;
WSADATA wsaData;
WORD wVersion;
wVersion = MAKEWORD(2, 2);
WSAStartup(wVersion, &wsaData);
*sock = socket(AF_INET, SOCK_DGRAM, 0);
if (*sock < 0)
{
printf("Socket create error!\r\n");
return FALSE;
}
timeval timev;
timev.tv_sec = 1;
timev.tv_usec = 0;
int ret = setsockopt(*sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timev, sizeof(timev));
SOCKADDR_IN sin;
memset(&sin, 0, sizeof(SOCKADDR_IN));
sin.sin_family = AF_INET;
sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
sin.sin_port = htons(Port);
if (::bind(*sock, (struct sockaddr*)&sin, sizeof(SOCKADDR_IN)) < 0)
{
printf("Socket bind error!\r\n");
return FALSE;
}
printf("Socket init success!\n");
return TRUE;
}
// UDP测试
bool MyProject::UDPCheck()
{
m_MsgLogEdit.ReplaceSel("正在检测UDP广播包,Open为泄漏,Close为未泄露。\r\n");
g_nCheckIndex ++;
int revLen = 0;
char revBuf[200000];
if (SOCKET_UDP_Init(&UDPSck))
{
g_bCheckList[g_nCheckIndex] = true;
DWORD startTime = GetTickCount();
while (GetTickCount() - startTime <= 2000)
{
revLen = recv(UDPSck, revBuf, 200000, 0);
if (revLen > 0)
{
g_bCheckList[g_nCheckIndex] = false;
break;
}
}
}
// 关闭通信
closesocket(UDPSck);
if (g_bCheckList[g_nCheckIndex])
{
stuCheckInfo.strUDPCheckState = "Close";
m_CheckList.SetItemBkColor(g_nCheckIndex, 2, RGB(0, 255, 0));
}
else
{
stuCheckInfo.strUDPCheckState = "Open";
m_CheckList.SetItemBkColor(g_nCheckIndex, 2, RGB(255, 0, 0));
}
m_CheckList.SetItemText(g_nCheckIndex, 2, stuCheckInfo.strUDPCheckState);
m_MsgLogEdit.ReplaceSel("UDP广播包检测完成\r\n");
return g_bCheckList[g_nCheckIndex];
}