TCP使用无效的连接块端口连接

时间:2016-06-15 20:54:10

标签: c++ sockets tcp-ip

我正在用c ++编写TCP通信脚本,以便在我的计算机和Aldebaran Nao机器人之间进行通信。

一般来说,我的脚本正在运行。但是,我遇到的麻烦是,当我从客户端调用connect时(当服务器应用程序关闭或以太网连接被删除时),我得到一个错误,表明操作正在进行中。

但是,一旦重新启动服务器应用程序/重新连接以太网电缆,我仍然无法调用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);
}

1 个答案:

答案 0 :(得分:1)

您的套接字是非阻止模式(您明确地执行此操作)。

因此,您的连接将立即返回“连接正在进行中”。当套接字是非阻塞的时,你需要在这个套接字上使用poll并等待它变得可读和/或可写 - 这意味着连接已经完成(成功与否)。

我认为更好的选择是使用阻塞套接字 - 我认为你没有理由在这里使用非阻塞调用。