2017-09-05 138 views
-3

我試圖爲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://stackoverflow.com/a/2597774/4581301我建議俯瞰答案和理由或採用差異。例如,你應該遵循他們的例子,並檢查'select'上的返回碼。 – user4581301

+0

'通信不起作用'不是問題描述。再試一次。 – EJP

+0

不工作意味着我的代碼連接後發送4個字節的請求,並收到14個字節的答案。與connectFUNC4它工作weel,但與FUNC3沒有通信wireshark檢測到。 – Dmitriy

回答

0

你的函數都沒有檢查任何返回值的錯誤。並且在非阻塞模式下撥打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; 
}