如何在UDP通信中的服务端和客户端 设置监听接收函数
recvfrom函数链接地址和端口, 都不是同局域网内地址,而是其他随机地址,具体原因排查后才真相大白!
之前第一版的代码中,设计由下位机为服务端,上位机软件只设置接收函数,点对点链接到服务端就可以。
最近更新的一版下位机程序,更换到FPGA处理,硬件工程师说是借用了其他的网络通信模块,下位机只设置了数据发送功能和通信端口+地址,结果第一版的上位机软件就读不到数据了。
原示例程序是可以接收下位机上报数据的,这就很纳闷了,费解啊 🥴😵😵💫🤯🤯
从网上找了个例子,关键代码如下:
WORD wVersionRequested = MAKEWORD(1, 1);
WSADATA wsaData;
int err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
std::string info = "WSASTAER FAILED WITH ERROR : ";
info = info.append(std::to_string(err));
OutputDebugStringA(info.c_str());
AfxMessageBox(CString(info.c_str()));
return;
}
if (LOBYTE(wsaData.wVersion) != 1 || HIBYTE(wsaData.wVersion) != 1)
{
std::string info = "COULD NOT FIND A USABLE VERSION OF WINSOCK.DLL";
OutputDebugStringA(info.c_str());
AfxMessageBox(CString(info.c_str()));
WSACleanup();
return;
}
else
{
std::string info = "THE WINSOCK.DLL 2.2 WAS FOUND OKAY";
OutputDebugStringA(info.c_str());
}
sockSrv = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); //创建一个socket句柄;
if (sockSrv == INVALID_SOCKET)
{
std::string info = "SOCKET FAILED WITH ERROR : ";
info = info.append(std::to_string(WSAGetLastError()));
OutputDebugStringA(info.c_str());
AfxMessageBox(CString(info.c_str()));
return;
}
CString csport;
GetDlgItem(IDC_ETPORT)->GetWindowTextW(csport);
USHORT dwport = atoi(CT2A(csport));
SOCKADDR_IN addrServ;
memset(&addrServ, 0, sizeof(addrServ));
addrServ.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(dwport);
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
setsockopt(sockSrv, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv));
auto ret = bind(sockSrv, (SOCKADDR*)&addrServ, sizeof(SOCKADDR));
if (ret == SOCKET_ERROR)
{
std::string info = "BIND FAILED WITH ERROR : ";
info = info.append(std::to_string(WSAGetLastError()));
OutputDebugStringA(info.c_str());
AfxMessageBox(CString(info.c_str()));
return;
}
bRunning = true;
GetDlgItem(IDC_BTSTART)->EnableWindow(FALSE);
GetDlgItem(IDC_BTSTOP)->EnableWindow(TRUE);
GetDlgItem(IDC_BTSEND)->EnableWindow(TRUE);
thid = std::thread(&GetDataThread, this);
thid.detach();
void GetDataThread()
{
int length = sizeof(SOCKADDR);
while (bRunning == true)
{
char recvBuf[100] = { 0 };
int len = recvfrom(sockSrv, recvBuf, 100, 0, (SOCKADDR*)&(addrClient), &length);
if (len <= 0 || std::string(recvBuf).length() <= 0)
{
Sleep(10);
continue;
}
PrintToList(CString(recvBuf), true);
OutputDebugStringA(recvBuf);
Sleep(10);
}
}
1、链接时 设置了监听函数,对任意地址和固定端口,来的数据都能监听接收
2、问题来了:recvfrom 接收到的端口和地址 都是随机的,每次软件重新打开都会有数据过来,但不是局域网下位机主动上报的数据
断点后,查看参数 (SOCKADDR*)&(addrClient) ,地址和端口始终不对。
3、解决
再原有的代码上修改后,始终存在这个问题,后续把处理上报数据的函数搬运到 示例程序中,仍然不可以。
最笨的办法:代码一点点注释,恢复成原有代码,才发现问题
第一版代码中引用了 vector,然后 using namespace std,注释掉就能正确接收下位机地址端口数据,但是百思不得姐😕
网络上也没找到相关的问题资料,有哪位遇到过或者懂的能解释下不, 这里先感谢各位大佬的解答和回复。
我是逃逸的卡路里,希望遇到的问题解答,对你有帮助。