简体   繁体   English

Winsock C ++连接超时

[英]Winsock C++ connect timeout

I'am trying to set my own timeot for connect() function. 我正在尝试为connect()函数设置自己的timeot。

my code works well with default connection like this: 我的代码在默认连接中效果很好,如下所示:

bool connectFUNC4(char * ipaddr) {

WSADATA wsa;
struct sockaddr_in server;

if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0)
return false;

if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
return false;

server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_family = AF_INET;
server.sin_port = htons(5577);

if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
    return false;
return true;
}

I understand idea with blocking and not blocking connection, and I've found solution with setting to nonblocking mode and timeout. 我了解阻塞和不阻塞连接的想法,并且我找到了设置为非阻塞模式和超时的解决方案。 It always finished successful but communication does not work. 它总是成功完成,但是通信不起作用。

bool connectFUNC3(char * ipaddr) {

WSADATA wsa;
struct sockaddr_in server;

server.sin_addr.s_addr = inet_addr(ipaddr);
server.sin_family = AF_INET;
server.sin_port = htons(5577);

unsigned long block = 1;
ioctlsocket((unsigned int)sock, FIONBIO, &block);

WSAGetLastError();

int ret = connect(sock, (struct sockaddr *)&server, sizeof(server));
timeval time_out;
time_out.tv_sec = 5;
time_out.tv_usec = 0; 

fd_set setW, setE;

FD_ZERO(&setW);
FD_SET(sock, &setW);
FD_ZERO(&setE);
FD_SET(sock, &setE);
select(0, NULL, &setW, &setE, &time_out);

bool flag;

if (FD_ISSET(sock, &setW))
{
    // connection successful
    flag = true;
}
else if (FD_ISSET(sock, &setE))
{
    // connection fail
    flag = false;
}
else
{
    // connection timeout
    flag = false;
}

block = 0;
ioctlsocket((unsigned int)sock, FIONBIO, &block);
return flag;
}

Please help to make it work, or to find another solution (multithread not usable in my case). 请帮助使其工作或找到其他解决方案(在我的情况下,多线程不可用)。 Thank you. 谢谢。

Neither of your functions are checking ANY return values for errors. 您的两个函数都没有检查任何返回值是否有错误。 And when calling select() in non-blocking mode, call it only if connect() fails with a WSAEWOULBLOCK error, and if select() then returns > 0 then you should be checking setE first and not setW . 在非阻塞模式下调用select()时,仅当connect()失败并出现WSAEWOULBLOCK错误时才调用它,并且如果select()然后返回> 0,则应首先检查setE而不是setW

Try something more like this: 尝试更多类似这样的方法:

void closesock(SOCKET *s)
{
    // preserve current error code
    int err = WSAGetLastError();
    closesocket(*sock);
    *sock = INVALID_SOCKET;
    WSASetLastError(err);
}

bool connectFUNC4(char * ipaddr)
{
    // you really shouldn't be calling WSAStartup() here.
    // Call it at app startup instead...

    struct sockaddr_in server = {0};
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(ipaddr);
    server.sin_port = htons(5577);

    // ipaddr valid?
    if (server.sin_addr.s_addr == INADDR_NONE)
        return false;

    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET)
        return false;

    if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
    {
        // connection failed
        closesock(&sock);
        return false;
    }

    // connection successful

    return true;
}

bool connectFUNC3(char * ipaddr)
{
    // you really shouldn't be calling WSAStartup() here.
    // Call it at app startup instead...

    struct sockaddr_in server = {0};
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(ipaddr);
    server.sin_port = htons(5577);

    // ipaddr valid?
    if (server.sin_addr.s_addr == INADDR_NONE)
        return false;

    sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (sock == INVALID_SOCKET)
        return false;

    // put socked in non-blocking mode...
    u_long block = 1;
    if (ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR)
    {
        closesock(&sock);
        return false;
    }

    if (connect(sock, (struct sockaddr *)&server, sizeof(server)) == SOCKET_ERROR)
    {
        if (WSAGetLastError() != WSAEWOULDBLOCK)
        {
            // connection failed
            closesock(&sock);
            return false;
        }

        // connection pending

        fd_set setW, setE;

        FD_ZERO(&setW);
        FD_SET(sock, &setW);
        FD_ZERO(&setE);
        FD_SET(sock, &setE);

        timeval time_out = {0};
        time_out.tv_sec = 5;
        time_out.tv_usec = 0; 

        int ret = select(0, NULL, &setW, &setE, &time_out);
        if (ret <= 0)
        {
            // select() failed or connection timed out
            closesock(&sock);
            if (ret == 0)
                WSASetLastError(WSAETIMEDOUT);
            return false;
        }

        if (FD_ISSET(sock, &setE))
        {
            // connection failed
            int err = 0;
            getsockopt(sock, SOL_SOCKET, SO_ERROR, &err, sizeof(err));
            closesock(&sock);
            WSASetLastError(err);
            return false;
        }
    }

    // connection successful

    // put socked in blocking mode...
    block = 0;
    if (ioctlsocket(sock, FIONBIO, &block) == SOCKET_ERROR)
    {
        closesock(&sock);
        return false;
    }

    return true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM