我正在做一个非常简单的游戏大厅系统。 每个客户端定期通过UDP广播两个数据包,以便最初发现其他客户端,并传输用户信息,准备就绪等。该游戏正在针对Windows和Linux(32和64位)进行开发。
在Windows方面,我已经得到了大厅系统完美的工作。 当我在一台Windows机器上进入大厅时,该人在其他机器中popup。 同样,立即检查和断开连接。 换句话说,它的工作。
现在的问题是:Linux。 networking代码实际上是相同的,只有less数必要的平台特定更改。 我第一次尝试Windows < – > Linux。 使用Wireshark的时候,我发现Linux方面的确在广播数据包,并从Windows中接收它们,但是游戏从来没有抓到数据包。 我发现我的select语句(套接字而不是套接字+ 1)的错误,但修复它并没有帮助。 Windows盒子正在广播数据包,但它根本没有收到来自Linux盒子的数据包!
然后我尝试了Linux Linux,但是发现即使两台机器都在广播和接收(再次通过Wireshark确认),两台机器上的游戏都不能“看见”数据包。
opencv ubuntu 12.04 Cmake错误:源目录不包含CmakeLists.txt
C ++中的Linux守护进程来处理PHP请求
我如何从源代码构buildlibpoppler?
在使用读写锁的pthread散列表中读取性能差
我很确定这不是一个防火墙问题(在任一平台上关掉所有东西,进行testing,恢复一切,没有变化),networking连接似乎没问题(可以手动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()),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,&time); if (selectResult == -1) { display_PError("select"); } else if (selectResult > 0) // 0 means it timed-out { int receivedBytes = recvfrom(linuxSocket,buffer,recvBufferLength,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?
编辑:这是套接字创build/设置代码,根据要求。 计算出的示例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,sizeof machineAddr); memset(&broadcastAddr,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; }
恢复中止下载?
Visual Studio 2010 MSVCR依赖项删除?
如何在Windows线程出口处的TLS插槽中释放对象?
C2440无法在C ++ WinApi中将LRESULT转换为WNDPROC
如果STDOUT缓冲区溢出,会发生什么情况
machineAddr.sin_port = htons(portNumber); inet_pton(AF_INET,&(machineAddr.sin_addr));
:
bind(linuxSocket,
这绑定套接字只接受发送到由GetIP返回的机器地址的portNumber数据包,这可能不是您想要的,因为您还希望接收发送到广播地址端口的数据包。 你可能想要将sin_addr设置为通配符地址INADDR_ANY ,这将允许套接字接收发送到端口的数据包,而这些地址以某种方式到达机器。
猜你忘了设置SO_broADCAST套接字选项,广播数据包被过滤掉。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。