2013-07-18 2 views
0

У меня очень простой TCP-клиент, как показано ниже. Проблема в том, что вызов connect() всегда возвращает 0, даже если на другой стороне нет сервера.TCP connect() всегда проходит

int TcpSend(struct sockaddr_in* ipv4_client, const void* buffer, size_t size) { 

    int sd_client = 0; 
    int status = -1; 

    // Grab an ipv4 TCP socket. 
    sd_client = socket(AF_INET, SOCK_STREAM, 0); 
    if (sd_client == -1) { 
     return -1; 
    } 

    // Make the socket non-blocking so that connect may fail immediately 
    status = fcntl(sd_client, F_SETFL, O_NONBLOCK); 
    if (status < 0) { 
     close(sd_client); 
     return -1; 
    } 

    // Bind and connect 
    status = connect(sd_client, (struct sockaddr*)ipv4_client, sizeof(*ipv4_client)); 
    if (status == -1) { 
     close(sd_client); 
     return -1; 
    } 

    printf("Status: %d %s\n", status, strerror(errno)); //// ??? : I always get status = 0 here 

    // Send a message to the server PORT on machine HOST. 
    // Ignore the fact that send might not have sent the complete data 
    status = send(sd_client, buffer, size, 0); //// Consequently I get a SIGPIPE here 
    if (status == -1) { 
     close(sd_client); 
     return -1; 
    } 

    close(sd_client); 

    return 0; 
} 

Я понимаю, что connect() будет проходить, если только привязка прошла успешно, и соединение не происходит. Однако это не должно происходить, когда розетка изготовлена ​​O_NONBLOCK. Код всегда проходит в connect(), и я получаю ошибку SIGPIPE внутри send().

ответ

2

Проблема была ipv4_client->sin_family каким-то образом 0.

Doing следующие исправления проблемы.

ipv4_client->sin_family = AF_INET; 
+0

Это не освобождает вас от необходимости выполнять дополнительную обработку или проверку ошибок, прежде чем вы начнете использовать сокет, если вы подключаетесь в неблокирующем режиме. Единственное практическое применение этого - снизить тайм-аут соединения по умолчанию. Если это не ваша цель, выполните подключение в режиме блокировки, а затем переключитесь. – EJP

+0

@EJP Я полностью согласен с тем, что мне нужна дополнительная проверка. Однако я был в тупике относительно того, почему 'connect()' не возвращал ошибку. Вопрос был больше на этих строках - Извините, если это вызвало какую-либо путаницу. – tinkerbeast

2

После того, как вы подключитесь в неблокирующем режиме, вам нужно вызвать select() с помощью FD-сокета в записываемом наборе, то есть дождаться, когда он станет доступен для записи, либо либо (1) проверить ошибки на сокете через getsockopt(),, либо (2) снова вызовите connect() и проверьте ошибку. Только после того, как все, что он действует начать называть send() или recv().

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