如何从TCP阻塞connect()调用中退出?

时间:2015-04-13 05:40:58

标签: c++ sockets tcp network-programming blocking

    int tcp_sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);    

    struct sockaddr_in remoteaddr;
    struct sockaddr_in localAddr;
    short local_port = 22222;
    short remote_port = 33333;

    // local addr
    localAddr.sin_family      = AF_INET;
    localAddr.sin_port        = htons(local_port);
    localAddr.sin_addr.s_addr = 0xC0A80AA5; // we don't give a shit
    int addrLen = sizeof(struct sockaddr_in);

    //Now bind TCP to local addr
    int result = bind(tcp_sock,(struct sockaddr*)&localAddr,addrLen);
    if (result < 0)
    {
        perror("\nbind failed");
        close(tcp_sock);
        return -1;
    }

    result = connect(tcp_sock, (struct sockaddr*)&remoteaddr, sizeof(struct sockaddr_in));
    printf("\nConnect returned %d, error no: %d", result, errno);

此处connect()呼叫在很长一段时间后失败。在我选择的时间后,有什么方法可以使connect函数返回?我尝试从另一个线程调用close(),但这不会改变任何内容。

3 个答案:

答案 0 :(得分:3)

在调用connect()之前将套接字置于非阻塞模式,然后您可以使用select()指定超时。 select()将告诉您连接是成功还是超时。如果成功,您可以根据需要将套接字重新置于阻止模式。如果失败/超时,请关闭套接字。

int tcp_sock = ::socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);    

...

int flags = fcntl(tcp_sock, F_GETFL, 0);
fcntl(tcp_sock, F_SETFL, flags | O_NONBLOCK);

result = connect(tcp_sock, ...);
if (result == -1)
{
    if (errno == EINPROGRESS)
    {
        fd_set wfd;
        FD_ZERO(&wfd);
        FD_SET(tcp_sock, &wfd);

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

        result = select(tcp_sock+1, NULL, &wrd, NULL, &timeout);
        if (result > 0)
        {
            // connected
            fcntl(tcp_sock, F_SETFL, flags);
        }
        else if (result == 0)
        {
            // time out
        }
        else
        {
            // error
        }
    }
}

答案 1 :(得分:1)

如果花费时间,那么摆脱连接的唯一方法就是使套接字无阻塞。如果它是一个阻塞套接字,你就无法离开。

  
    

在我选择的时间后,有什么方法可以让连接函数返回?

  

您的选择是将套接字标记为非阻塞。别无他法。阻塞意味着“阻塞”执行线程,直到套接字上发生事件为止。您不能根据需要使用阻塞套接字和超时。

使用selectepoll机制来监控套接字。

答案 2 :(得分:1)

  

在我选择的时间后,有什么方法可以让连接函数返回?

向该过程发送信号。

#define TIME_OUT_SECONDS (15)

void alarm_handler(int sig)
{
   /* Do nothing. */
}

int main(void)
{
  ...

  signal(alarm_handler);
  alarm(TIME_OUT_SECONDS);

  result = connect(tcp_sock, ...);

  ...
相关问题