Socket客户端重复等待服务器在C++中连接

huangapple go评论64阅读模式
英文:

Socket client repeatedly wait for server in connect c++

问题

我想要问一下,如何让套接字客户端重复等待服务器。例如,如果套接字服务器未运行,那么在connect()期间客户端会等待大约1-3秒,然后抛出错误10038(WSAENOTSOCK)。如果服务器准备好,它会连接。

我希望客户端在服务器无法访问时等待。是否有任何标志可以实现这一点?我尝试将connect()放入while()循环中,但没有用。

以下是重要的代码部分:

#define SOCKET_DEFAULT_PROTOCOL SOCK_STREAM

typedef struct dev_socket {
    std::string ip = "";
    std::thread openner;
    unsigned short port = 0;
    SOCKET num = 0, external_num = 0;
} dev_socket;

int openClientSocket(dev_socket &io, std::string server_ipv4, unsigned short port) {
    char *server_name = (server_ipv4.empty() ? localhost_addr : const_cast<char*>(server_ipv4.c_str()));
    int retval, socket_type = SOCKET_DEFAULT_PROTOCOL;
    struct sockaddr_in server;
    struct hostent *hp;
#if defined(_WIN32)
    int fromlen;
#else
    socklen_t fromlen;
#endif

#if defined(_WIN32)
    WSADATA wsaData;
    if ((retval = WSAStartup(MAKEWORD(2, 0), &wsaData)) != 0) {
        cout << "ERROR! Client: WSAStartup() failed (socket number " + std::to_string(io.num) +
            ") with error " + std::to_string(retval) + ".\n";
        WSACleanup();
        return 1;
    }
#endif

    // 尝试检测是否应该调用gethostbyname()还是gethostbyaddr()
    hp = gethostbyname(server_name);
    if (hp == NULL) {
        cout << "ERROR! Client: Cannot resolve address \"" + (std::string)(server_name) + "\": Error.\n";
        cleenup();
        return 1;
    }

    // 创建套接字
    // 将解析的信息复制到sockaddr_in结构中
    memset(&server, 0, sizeof(server));
    memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
    server.sin_family = hp->h_addrtype;
    server.sin_port = htons(port);
    io.num = socket(AF_INET, socket_type, 0); /* 打开套接字 */
    if (io.num < 0) {
        cout << "ERROR! Client: Error Opening socket number " + std::to_string(io.num) + ". " + getSocketErrorOrNewLine();
        cleenup();
        return 1;
    }

    // 连接
    if ((connect(io.num, (struct sockaddr*)&server, sizeof(server))) == -1) {
        cout << "ERROR! Client: connect() failed (socket number " + std::to_string(io.num) + "). " + getSocketErrorOrNewLine();
        cleenup();
        return 1;
    }
}

非常感谢您的回答。

英文:

I would like to ask, how to make socket client repeatedly waiting for server. For example if socket server is not running, then client is waiting about 1-3 seconds during connect() and then throw error 10038 (WSAENOTSOCK). If server is ready, then it connects.

I want the client wait if server is unreachable. Is there any flag for this? I tried to put connect() into while() loop but it was not useful.

Here is the important fromcode

#define SOCKET_DEFAULT_PROTOCOL SOCK_STREAM
typedef struct dev_socket {
std::string ip = "";
std::thread openner;
unsigned short port = 0;
SOCKET num = 0, external_num = 0;
}dev_socket;
int openClientSocket(dev_socket &io, std::string server_ipv4, unsigned short port) {
char *server_name = (server_ipv4.empty() ? localhost_addr : const_cast<char*>(server_ipv4.c_str()));
int retval, socket_type = SOCKET_DEFAULT_PROTOCOL;
struct sockaddr_in server;
struct hostent *hp;
#if defined(_WIN32)
int fromlen;
#else
socklen_t fromlen;
#endif
#if defined(_WIN32)
WSADATA wsaData;
if ((retval = WSAStartup(MAKEWORD(2, 0), &wsaData)) != 0) {
cout << "ERROR! Client: WSAStartup() failed (socket number " + std::to_string(io.num) +
") with error " + std::to_string(retval) + ".\n";
WSACleanup();
return 1;
}
#endif
// Attempt to detect if we should call gethostbyname() or gethostbyaddr()
hp = gethostbyname(server_name);
if (hp == NULL) {
cout << "ERROR! Client: Cannot resolve address \"" + (std::string)(server_name) + "\": Error.\n";
cleenup();
return 1;
}
//Creating SOCKET
// Copy the resolved information into the sockaddr_in structure
memset(&server, 0, sizeof(server));
memcpy(&(server.sin_addr), hp->h_addr, hp->h_length);
server.sin_family = hp->h_addrtype;
server.sin_port = htons(port);
io.num = socket(AF_INET, socket_type, 0); /* Open a socket */
if (io.num < 0) {
cout << "ERROR! Client: Error Opening socket number " + std::to_string(io.num) + ". " + getSocketErrorOrNewLine();
cleenup();
return 1;
}
//CONNECTing
if ((connect(io.num, (struct sockaddr*)&server, sizeof(server))) == -1) {
cout << "ERROR! Client: connect() failed (socket number " + std::to_string(io.num) + "). " + getSocketErrorOrNewLine();
cleenup();
return 1;
}
}

Thank you in advance for your answers.

UPDATE: The while() loop is working (but probably not best) solution - there was bug in testing api.

答案1

得分: 0

"很多人都写过,while循环是唯一的方法。我希望有一种“漂亮”的解决方案,但这也可以。"

英文:

As many of you wrote, the while cycle is the only way. I hoped that there is some "pretty" solution, but this is also fine.

huangapple
  • 本文由 发表于 2023年3月15日 17:59:02
  • 转载请务必保留本文链接:https://go.coder-hub.com/75743119.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定