Winsock C++连接超时

Winsock C++连接超时

问题描述:

我试图为connect()函数设置自己的时间。Winsock C++连接超时

我的代码以这样的默认连接工作得很好:

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

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

+0

你似乎有这个答案的修改版本:https://*.com/a/2597774/4581301我建议俯瞰答案和理由或采用差异。例如,你应该遵循他们的例子,并检查'select'上的返回码。 – user4581301

+0

'通信不起作用'不是问题描述。再试一次。 – EJP

+0

不工作意味着我的代码连接后发送4个字节的请求,并收到14个字节的答案。与connectFUNC4它工作weel,但与FUNC3没有通信wireshark检测到。 – Dmitriy

你的函数都没有检查任何返回值的错误。并且在非阻塞模式下拨打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; 
}