gpt4 book ai didi

c++ - 正在发送 UDP 广播,但未收到

转载 作者:太空狗 更新时间:2023-10-29 21:06:33 26 4
gpt4 key购买 nike

我正在为一款游戏开发一个非常简单的大厅系统。每个客户端定期通过 UDP 广播两个数据包,以初步发现其他客户端并传输用户信息、准备情况等。该游戏正在为 Windows 和 Linux(32 位和 64 位)开发。

在 Windows 端,我已经让大厅系统完美运行。当我在一台 Windows 机器上进入大厅时,这个人会在其他机器上弹出。同样,立即检测就绪检查和断开连接。换句话说,它有效。

现在的问题是:Linux。网络代码实际上是相同的,只有少数必要的特定于平台的更改。我首先尝试了 Windows<->Linux。使用Wireshark,我发现Linux端确实在广播数据包并从Windows盒子接收数据包,但游戏从未捕获数据包。我在我的 select 语句中发现了一个错误(socket 而不是 socket + 1),但修复它没有帮助。 Windows 机器正在广播数据包,但它根本没有从 Linux 机器接收数据包!

然后我尝试了 Linux<->Linux,但发现即使两台机器都在广播和接收(再次通过 Wireshark 确认),但两台机器上的游戏都无法“看到”数据包。

我很确定这不是防火墙问题(在任何一个平台上都关闭、测试、重新打开一切,没有任何变化)并且网络连接似乎正常(能够手动 ping 每个主机)。我还检查以确保端口确实可用(它们是可用的)。

下面是广播数据包的代码:

    void NetworkLinux::BroadcastMessage(const std::string &msg,
const char prefix)
{
string data(prefix + msg);

if (sendto(linuxSocket, data.c_str(), static_cast<int>(data.length()), 0,
reinterpret_cast<sockaddr*>(&broadcastAddr), sizeof(broadcastAddr)) == -1)
{
Display_PError("sendto");
}
}

以及接收数据包的代码:

const Message NetworkLinux::ReceiveMessage()
{
char buffer[recvBufferLength];
fill(buffer, buffer + recvBufferLength, 0);
sockaddr_in sender;
int senderLen = sizeof(sender);

fd_set read_fds;
FD_ZERO(&read_fds);
FD_SET(linuxSocket, &read_fds);

timeval time;
time.tv_sec = 0;
time.tv_usec = 16667; // microseconds, so this is ~1/60 sec

int selectResult = select(linuxSocket + 1, &read_fds,
nullptr, nullptr, &time);
if (selectResult == -1)
{
Display_PError("select");
}
else if (selectResult > 0) // 0 means it timed-out
{
int receivedBytes = recvfrom(linuxSocket, buffer,
recvBufferLength, 0, reinterpret_cast<sockaddr*>(&sender),
reinterpret_cast<socklen_t*>(&senderLen));

if (receivedBytes == -1)
{
Display_PError("recvfrom");
}
else if (receivedBytes > 0)
{
Message msg;
msg.prefix = buffer[0];
msg.msg = string(buffer + 1, buffer + receivedBytes);
msg.address = sender.sin_addr;
return msg;
}
}
Message m;
m.prefix = 'N';
return m;
}

当我看到数据包到达时,为什么 select() 一直返回 0?还有,为什么在Windows<->Windows场景下可以,而在Linux<->Linux或者Linux<->Windows场景下不行呢?

编辑:根据要求,这是套接字创建/设置代码。计算出的示例 IP/广播地址为:192.168.1.3/192.168.1.255、192.168.1.5/192.168.1.255,与 Windows 端生成和使用的匹配。

bool NetworkLinux::StartUp()
{
// zero addr structures
memset(&machineAddr, 0, sizeof machineAddr);
memset(&broadcastAddr, 0, sizeof broadcastAddr);

// get this machine's IP and store it
machineAddr.sin_family = AF_INET;
machineAddr.sin_port = htons(portNumber);
inet_pton(AF_INET, GetIP().c_str(), &(machineAddr.sin_addr));

// get the netmask and calculate/store the correct broadcast address
broadcastAddr.sin_family = AF_INET;
broadcastAddr.sin_port = htons(portNumber);
GetNetMask();
broadcastAddr.sin_addr.s_addr = machineAddr.sin_addr.s_addr | ~netmask;

char bufIP[INET_ADDRSTRLEN], bufBroadcast[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &machineAddr.sin_addr, bufIP, INET_ADDRSTRLEN);
inet_ntop(AF_INET, &broadcastAddr.sin_addr, bufBroadcast,
INET_ADDRSTRLEN);
Log("IP is: " + string(bufIP) + "\nBroadcast address is: "
+ string(bufBroadcast));

// create socket
linuxSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (linuxSocket == -1)
{
Display_PError("socket");
return false;
}
Log("Socket created.");

// switch to broadcast mode
int broadcast = 1;
if (setsockopt(linuxSocket, SOL_SOCKET, SO_BROADCAST, &broadcast,
sizeof broadcast) == -1)
{
Display_PError("setsockopt");
close(linuxSocket);
return false;
}
Log("Socket switched to broadcast mode.");

// bind it (this simplifies things by making sure everyone is using the same port)
if (bind(linuxSocket, reinterpret_cast<sockaddr*>(&machineAddr),
sizeof(machineAddr)) == -1)
{
Display_PError("bind");
close(linuxSocket);
return false;
}
Log("Socket bound.");

return true;
}

最佳答案

machineAddr.sin_port = htons(portNumber);
inet_pton(AF_INET, GetIP().c_str(), &(machineAddr.sin_addr));

:

bind(linuxSocket, reinterpret_cast<sockaddr*>(&machineAddr),

这将套接字绑定(bind)为仅接受发送到 GetIP 返回的机器地址处的 portNumber 的数据包,这可能不是您想要的,因为您也想接收发送到广播地址端口的数据包。您可能希望将 sin_addr 设置为通配符地址 INADDR_ANY,这将允许套接字接收发送到以某种方式到达机器的任何地址端口的数据包。

关于c++ - 正在发送 UDP 广播,但未收到,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7496761/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com