2016-06-15 2 views
0

Я пишу сценарий связи TCP в C++ для связи между моим компьютером и роботом Aldebaran Nao.TCP Connect with Invalid Connection Blocks Порт

В целом мой скрипт работает. Тем не менее, проблема, с которой я столкнулась, заключается в том, что когда я вызываю соединение с клиентом (когда приложение сервера закрыто или соединение ethernet удалено), я получаю сообщение об ошибке, выполняемой этой операцией.

Однако, как только приложение сервера перезагрузится/подключен кабель Ethernet, я все равно не могу позвонить connect для успешного восстановления соединения. Я все еще получаю сообщение о том, что операция выполняется.

В качестве примечания, когда мой клиент определяет, что соединение не может быть выполнено, дескриптор сокета закрывается перед повторной попыткой подключения. Вот мой код для подключения на стороне клиента:

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

TCPStream* TCPConnector::connect(const char* serverIP, int port, int timeoutSec) 
{ 
    if (timeoutSec == 0) 
    { 
     return connect(serverIP, port); 
    } 

    struct sockaddr_in address; 

    // Store all zeros for address struct. 
    memset(&address, 0, sizeof(address)); 

    // Configure address struct. 
    address.sin_family = AF_INET; 
    address.sin_port = htons(port); // Convert from host to TCP network byte order. 
    inet_pton(PF_INET, serverIP, &(address.sin_addr)); // Convert IP address to network byte order. 

    // Create a socket. The socket signature is as follows: socket(int domain, int type, int protocol) 
    int sd = socket(AF_INET, SOCK_STREAM, 0); 

    int optval = 1; 

    if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof optval) == -1) 
    { 
     std::cout << "failed to set socket option" << std::endl; 
    } 

    // Set socket to be non-blocking. 
    int arg; 
    arg = fcntl(sd, F_GETFL, NULL); 
    arg |= O_NONBLOCK; 
    fcntl(sd, F_SETFL, arg); 

    // Connect with time limit. 
    fd_set set; 
    FD_ZERO(&set); // Clear the set. 
    FD_SET(sd, &set); // Add our file descriptor to the set. 

    struct timeval timeout; 
    timeout.tv_sec = timeoutSec; 
    timeout.tv_usec = 0; 

    // If the connect call returns 0, then the connection was established. Otherwise, 
    // check if the three-way handshake is underway. 
    if (::connect(sd, (struct sockaddr *)&address, sizeof(address)) < 0) 
    { 
     // If the handshake is underway. 
     if (errno == EINPROGRESS) 
     { 
      std::cout << "handshake in progress" << std::endl; 

      // Designate timeout period. 
      int ret = select(sd + 1, NULL, &set, NULL, &timeout); 

      std::cout << "return value from select : " << ret << std::endl; 

      // Check if timeout or an error occurred. 
      if (ret <= 0) 
      { 
       return NULL; 
      } 
      else 
      { 
       // Check if select returned 1 due to an error. 
       int valopt; 
       socklen_t len = sizeof(int); 

       getsockopt(sd, SOL_SOCKET, SO_ERROR, (void*)(&valopt), &len); 

       if (valopt) 
       { 
        char * errorMessage = strerror(errno); // get string message from errn 
        std::string msg (errorMessage); 
        std::cout << msg << std::endl; 


        return NULL; 
       } 
      } 
     } 
     else 
     { 
      return NULL; 
     } 
    } 

    // Return socket to blocking mode 
    arg = fcntl(sd, F_GETFL, NULL); 
    arg &= (~O_NONBLOCK); 
    fcntl(sd, F_SETFL, arg); 

    // Create stream object. 
    return new TCPStream(sd, &address); 
} 
+0

Он не блокирует порт. Вы вводите код в бесконечный цикл. – EJP

+0

@EJP Не могли бы вы объяснить, что вызывает бесконечный цикл? – Austin

ответ

1

Ваш сокет неблокирует режим (вы делаете это явно).

В результате ваше соединение немедленно вернется с «соединением». Если сокет не блокируется, вам понадобится poll на этом сокете и дождитесь, когда он станет читаемым и/или записанным - это означает, что соединение завершено (успешно или нет).

Лучшим вариантом в моем представлении будет использование блокирующих сокетов - я не вижу причин использовать здесь неблокирующий вызов.

+0

Я включил неблокирующие сокеты, чтобы мое клиентское приложение могло продолжить работу, даже если соединение было невозможно. Сразу после установки сокета для неблокирования я использую select для опроса для ответа за определенный период таймаута. – Austin

+1

Правильный подход, если вы не пишете для Windows (используйте overlapped io), но это не поможет вам с подключением. Так или иначе вам придется ждать завершения или неудачи подключения, как сказал Сергей. С другой стороны, похоже, что вы находитесь в том же направлении, что и boost :: asio (http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio.html). Вероятно, стоит потратить ваше время на то, чтобы сжечь слишком много времени, заново изобретая колесо. – user4581301

+0

@ Аустин, в чем смысл? Вы все еще ожидаете результата подключения. Просто сделайте блокирующую розетку и сберегите много забот. – SergeyA

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

  • Нет связанных вопросов^_^