【发布时间】:2021-02-19 21:51:21
【问题描述】:
我有一个客户端,它等待服务器向特定端口发送广播,然后返回消息。
我可以在 Wireshark 中看到数据包,但我的应用程序没有捕获它。
这是捕获数据包的函数。 (getPrivateIP 有效)
uint32_t findMastersIP()
{
sockaddr_in recvAddr{};
sockaddr_in sendAddr{};
SOCKET s = socket(AF_INET, SOCK_DGRAM, 0);
if (s == INVALID_SOCKET)
std::cout << "Socket error <" << WSAGetLastError() << ">" << std::endl;
int opt;
std::string message, response;
char* buf = new char[65536];
int fromlen;
recvAddr.sin_addr.s_addr = getPrivateIP();
recvAddr.sin_port = htons(667);
recvAddr.sin_family = AF_INET;
fromlen = sizeof(recvAddr);
opt = 1;
if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (const char*)&opt, sizeof(opt))<0)
std::cout << "Sockopt error <" << WSAGetLastError() << ">" << std::endl;
if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, (const char*)&opt, sizeof(opt)) < 0)
std::cout << "Sockopt error <" << WSAGetLastError() << ">" << std::endl;
if(bind(s, (sockaddr*)&recvAddr, sizeof recvAddr) < 0)
std::cout << "Bind error <" << WSAGetLastError() << ">" << std::endl;
/*fixed messages for my "protocol"*/
message = "What is your IP?";
response = "My IP";
/*wait for the master to ask me to connect*/
do {
ZeroMemory(buf, 65536);
if(recvfrom(s, buf, 65536, 0, (sockaddr*)&recvAddr, &fromlen) <= 0)
{
std::cout << "Recieve error <" << WSAGetLastError() << ">" << std::endl;
goto errorLable;
}
std::cout << buf << std::endl;
} while (!std::string(buf)._Equal(message));
if(sendto(s, response.c_str(), response.size(), 0, (sockaddr*)&recvAddr, sizeof(recvAddr)) <= 0)
std::cout << "Send error <" << WSAGetLastError() << ">" << std::endl;
errorLable:
delete[] buf;
closesocket(s);
return recvAddr.sin_addr.s_addr;
}
奇怪的是,当服务器和客户端在同一台计算机上时它可以工作,但当它们在两台不同的计算机上时就不行。
有人知道是什么原因造成的吗?以及如何解决?
【问题讨论】:
-
战术说明:如果你将
do/while循环和随后的if移动到一个函数中,当你收到错误或消息时将return从函数中移动,你赢了'在代码审查期间不必浪费时间与goto语句争吵。 -
recvAddr.sin_addr.s_addr = getPrivateIP();看起来您只接受来自getPrivateIP返回的任何消息。因为我不知道它返回什么,所以我不能确定这是否是你想要的,但如果不是,你会得到你所看到的行为。 -
它返回我的ip,“10.0.0.8”,它不会接受广播消息吗?
-
我在广播方面很弱,从未尝试将广播消息侦听器绑定到单个发件人,所以我可能大错特错,但通常如果您绑定到特定地址,您只接受来自该地址的消息地址。如果您不在乎是谁在发送消息,请使用
INADDR_ANY。 -
@LeoSegol 与您的问题无关:您不需要
SO_BROADCAST来接收广播,只需发送广播。在调用recvfrom()之前,您的循环不会在每次迭代中重置fromlen。recvfrom()返回 0 不是错误情况。buf不保证是空终止的,除非发送方正在发送空终止数据,使用recvfrom()的返回值知道buf的实际长度。std::string没有_Equal()方法,请改用其operator==或compare()方法。调用 `sendto(