2009-10-20 516 views
2

我在linux上使用C++中的套接字連接到使用connect()的服務器,但它似乎沒有超時值。給它幾秒鐘暫停的最簡單/最好的方法是什麼?我會後我有最多的代碼,包括阻塞調用連接():在C++中使用connect()時設置超時

using namespace std; 
int main(int argc, char* argv[]) 
{ 
    // Interpret the command line arguments 
    string uri_string = ""; 

    if (argc != 2) 
    { 
    cerr << "Usage: " << argv[0]; 
    cerr << " <URI>" << endl; 
    return 1; 
    } 
    else 
    { 
    uri_string = argv[1]; 
    } 

    // Create URI object and have it parse the uri_string 
    URI *uri = URI::Parse(uri_string); 

    if (uri == NULL) 
    { 
    cerr << "Error: Cannot parse URI." << endl; 
    return 2; 
    } 

    // Check the port number specified, if none use port 80 
    unsigned port = 80; 
    if (uri->Is_port_defined()) 
    { 
    port = uri->Get_port(); 
    } 

    // Create TCP socket and connect to server 
    int tcp_sock = socket(AF_INET, SOCK_STREAM, 0); 
    if (tcp_sock < 0) 
    { 
    cerr << "Unable to create TCP socket." << endl; 
    return 3; 
    } 

    sockaddr_in server; 
    socklen_t slen = sizeof(server); 

    server.sin_family = AF_INET; 
    server.sin_port = htons(port); 
    cout << "Resolving " << uri->Get_host() << "... "; 
    hostent *hostp = gethostbyname(uri->Get_host().c_str()); 
    memcpy(&server.sin_addr, hostp->h_addr, hostp->h_length); 

    struct in_addr **pptr; 
    pptr = (struct in_addr **)hostp->h_addr_list; 

    string ip_addr = ""; 
    while(*pptr != NULL) { 
    ip_addr += inet_ntoa(**(pptr++)); 
    } 
    cout << ip_addr << endl; 

    cout << "Connecting to " << uri->Get_host() << "|" << ip_addr << "|:"; 
    cout << port << "... "; 
    if (connect(tcp_sock, (sockaddr*)&server, slen) < 0) 
    { 
    cerr << "Unable to connect to server via TCP." << endl; 
    close(tcp_sock); 
    return 4; 
    } 
    cout << "connected." << endl; 

    // rest of code 
} 

回答

5

使套接字成爲非阻塞套接字,然後使用帶有超時值的select()或poll()來檢查可寫性。如果select()以超時返回,您沒有及時連接,並且可以關閉套接字並處理連接失敗。如果它返回完成,一切都很好,你可以繼續。

1

this newsgroup post看看,用細節和示例代碼如何把一個超時的套接字連接在Lunux。基本思想是使用非阻塞套接字,然後等待連接。

1

爲您的套接字設置非阻塞模式並使用select檢查連接是否已建立。 here是樣本

+3

儘管這個鏈接可能回答這個問題,但最好在這裏包含答案的基本部分並提供參考鏈接。如果鏈接頁面更改,則僅鏈接答案可能會失效。 - [來自評論](/評論/低質量帖/ 16911940) – wasthishelpful 2017-08-03 08:24:51

1

如果沒有select()的痛苦,做非阻塞的另一種方法是檢查EWOULDBLOCK的GetLastError()。

// set socket as nonblocking 
unsigned long value = 1; 
if (ioctlsocket(yourSocket, FIONBIO, &value) == SOCKET_ERROR) 
    return SOCKET_ERROR; 

// (call connect here) 

// check if connect would block 
if (GetLastError() == EWOULDBLOCK) 
    return TIMEOUT; 
+0

這絕對是最簡單的,我會試試看。謝謝。 – adhanlon 2009-10-21 00:40:32

+0

這樣做的問題是任何阻塞的連接嘗試都會失敗。如果你連接到另一臺機器上的東西,那可能是每一次嘗試。 – janm 2009-10-21 23:14:58

+0

我必須使用什麼#include使用ioctlsocket,FIONBIO,SOCKET_ERROR,GetLastError(),TIMEOUT – adhanlon 2009-10-22 05:17:18