【问题标题】:Winsock C++ connect timeoutWinsock C++ 连接超时
【发布时间】:2017-09-05 00:30:31
【问题描述】:

我正在尝试为 connect() 函数设置我自己的时间。

我的代码适用于这样的默认连接:

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;
}

我理解阻塞和非阻塞连接的想法,并且我找到了设置为非阻塞模式和超时的解决方案。它总是成功完成,但通信不起作用。

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;
}

请帮助使其工作,或找到另一个解决方案(多线程在我的情况下不可用)。谢谢。

【问题讨论】:

  • 您似乎有此答案的修改版本:stackoverflow.com/a/2597774/4581301 我建议查看答案并证明或采用差异。例如,您应该按照他们的示例检查select 上的返回码。
  • '通讯不工作'不是问题描述。再试一次。
  • 不工作意味着我的代码在连接后发送 4 字节请求并收到 14 字节应答。使用 connectFUNC4 它可以正常工作,但使用 FUNC3 时,wireshark 没有检测到通信。
  • 在 Func3 中,您不检查连接调用的返回值。 connect的返回值见文档下的备注:msdn.microsoft.com/en-us/library/windows/desktop/…
  • 那么 FUNC3 和 connectFUNC4 到底是什么?

标签: c++ winsock connection-timeout


【解决方案1】:

您的两个函数都没有检查任何返回值是否有错误。在非阻塞模式下调用select() 时,仅当connect() 失败并出现WSAEWOULBLOCK 错误时调用它,如果select() 然后返回> 0,那么您应该首先检查setE 而不是setW .

试试这样的:

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;
}

【讨论】:

    猜你喜欢
    • 2011-10-04
    • 2023-03-17
    • 2011-11-06
    • 1970-01-01
    • 2013-04-14
    • 1970-01-01
    • 2023-03-05
    • 2016-06-20
    • 2020-07-08
    相关资源
    最近更新 更多