我尝试使用rcon协议与服务器通信以控制游戏服务器。到目前为止,我正在使用一个现有的C#库,但这个库有时非常错误,因此我正在用C ++编写自己的应用程序,以便我能够在Windows和Linux上使用它服务器
到目前为止,这个问题很顺利,但是当我尝试使用select()设置超时以查明服务器是否仍然启动并响应我的命令时,我遇到了问题。在应用程序的第一次运行期间,select()始终返回正确的值,但在关闭并再次运行它之后,结果会变得奇怪。
我的代码看起来很像:
#include <stdio.h>
#include <iostream>
#include <iomanip>
#include <sstream>
#include <string.h>
#include <unistd.h>
// Socket Includes
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// Other Includes
#include "main.h"
#include "crc32.h"
int main() {
struct sockaddr_in server;
int mysocket, slen = sizeof(server);
char buffer[2048];
if ((mysocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0)
printf("error creating socket");
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("xxx.xxx.xxx.xxx");
server.sin_port = htons(1234);
if(connect(mysocket, (sockaddr*) &server, sizeof(server)) < 0)
printf("error connecting the socket");
bool isConnected = false;
/*
Creating the Packet to send, cut to save some space
*/
sendto(mysocket, loginPacket.c_str(), loginPacket.length(), 0, (sockaddr *) &server, slen);
while(1) {
// clearing the buffer
bzero(buffer, 2048);
// Timeout Settings
int selectSize = 0;
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
fd_set fds;
FD_ZERO(&fds);
FD_SET(mysocket, &fds);
selectSize = select(mysocket + 1, &fds, 0, 0, &timeout);
std::cout << "Size is: " selectSize << std::endl; // just for testing :)
if (selectSize == 1) {
int recvLength = recvfrom(mysocket, buffer, sizeof(buffer), 0, (sockaddr *) &server, (socklen_t*) &slen);
if (buffer[7] == 0x00) {
if (buffer[8] == 0x01) {
//password correct
isConnected = true;
break;
}
if (buffer[8] == 0x00) {
//password wrong, do sth.
}
}
}
}
// tests
sayHello();
close(mysocket);
return 0;
}
当我第一次启动脚本并且服务器未启动时,一切都按预期工作,5秒后selectSize返回值0.它继续循环直到我启动服务器,然后它将返回值1并打破while循环。然后我退出应用程序,关闭服务器并再次启动脚本。它不会在5秒后返回值0,而是立即返回值1(即使服务器处于脱机状态并且没有要接收的数据包),然后在5秒后它将返回值0.运行相同的脚本(有一些Windows上的调整给了我几乎相同的结果,但是selectSize几乎总是返回1,即使服务器处于脱机状态且值应该为0.我读了大量关于使用select()正确方法的网站但没有他们帮助了我,因为select()在退出并重新启动应用程序后没有返回可靠的结果。
P.S。:有一些关于如何正确使用select()的令人困惑的信息,我几乎使用了互联网上提供的每个解决方案,如:
selectSize = select(mysocket + 1, &fds, 0, 0, &timeout);
selectSize = select(0, &fds, 0, 0, &timeout);
selectSize = select(1, &fds, 0, 0, &timeout);
但他们都没有给我一个可靠的结果。