2017-09-05 3 views
-3

Ich versuche, meine eigene Zeit für die Funktion connect() einzustellen.Winsock C++ Verbindungszeitüberschreitung

mein Code funktioniert gut mit Standard-Verbindung wie folgt aus:

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 Idee verstehen mit blockierenden und nicht die Verbindung zu blockieren, und ich habe festgestellt Lösung nicht blockierenden Modus und Timeout bei der Einstellung. Es endete immer erfolgreich, aber die Kommunikation funktioniert nicht.

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

Bitte helfen Sie es zu arbeiten, oder eine andere Lösung zu finden (Multithread nicht in meinem Fall verwendbar). Vielen Dank.

+0

Sie scheinen eine modifizierte Version dieser Antwort zu haben: https://stackoverflow.com/a/2597774/4581301 empfehle ich die Antwort über und zu rechtfertigen oder zu erlassen suchen die Unterschiede. Zum Beispiel sollten Sie ihrem Beispiel folgen und den Rückgabecode auf 'select' überprüfen. – user4581301

+0

"Kommunikation funktioniert nicht" ist keine Problembeschreibung. Versuch es noch einmal. – EJP

+0

Nicht arbeiten bedeutet, dass mein Code nach der Verbindung 4 Byte Anfrage senden und 14 Bytes beantworten. mit connectFUNC4 funktioniert es weel, aber mit FUNC3 wurde keine Kommunikation von wireshark erkannt. – Dmitriy

Antwort

0

Keine Ihrer Funktionen überprüft ANY-Rückgabewerte auf Fehler. Und wenn Sie select() im nicht blockierenden Modus aufrufen, rufen Sie ihn nur auf, wenn connect() mit einem Fehler WSAEWOULBLOCK fehlschlägt, und wenn select() dann> 0 zurückgibt, sollten Sie zuerst setE überprüfen und nicht setW.

etwas mehr wie die Sie interessieren:

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