2009-10-20 3 views
2

Я использую сокеты в C++ для linux для подключения к серверу с помощью connect(), но у него нет значения тайм-аута. Каким будет самый простой/лучший способ дать ему паузу в несколько секунд. Я отправлю код у меня есть до, и в том числе, вызов блокировки для подключения():Установка таймаута при использовании connect() в C++

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

Хотя эта ссылка может ответить на вопрос, лучше включить основные части ответа здесь и предоставить ссылку для справки. Ответные ссылки могут стать недействительными, если связанная страница изменится. - [Из обзора] (/ review/low-quality-posts/16911940) – wasthishelpful

1

Другой способ сделать без блокировки без боли select() - проверить GetLastError() для EWOULDBLOCK.

// 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

+0

Проблема заключается в том, что любая попытка соединения, которая будет блокироваться, завершится с ошибкой. И если вы подключаетесь к чему-то на другой машине, это, вероятно, будет каждая попытка. – janm

+0

что я должен # включить для использования ioctlsocket, FIONBIO, SOCKET_ERROR, GetLastError(), TIMEOUT – adhanlon

Смежные вопросы