超时和select()无法按预期工作

时间:2016-08-08 11:51:30

标签: c++ sockets

我尝试使用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);

但他们都没有给我一个可靠的结果。

0 个答案:

没有答案