如何摆脱 TCP 阻塞 connect() 调用?

How to get out from a TCP blocking connect() call?

    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 在我选择的时间后发挥 return 的作用吗?我尝试从另一个线程调用 close() 但这并没有改变任何东西。

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

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);

int errCode = 0;

result = connect(tcp_sock, ...);
if (result < 0)
{
    errCode = errno;

    if (errCode == 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, &wfd, NULL, &timeout);
        if (result > 0)
        {
            socklen_t len = sizeof(errCode);
            result = getsockopt(tcp_sock, SOL_SOCKET, SO_ERROR, &errCode, &len);
            if (result < 0)
                errCode = errno;
            else
                result = (errCode == 0) ? 0 : -1;
        }
        else if (result == 0)
        {
            errCode = ETIMEDOUT;
            result = -1;
        }
        else
        {
            errCode = errno;
        }
    }
}

if (result == 0)
{
    // connected
    fcntl(tcp_sock, F_SETFL, flags);
    ...
}
else
{
    // error, use errCode as needed
    ...
}

如果花费时间,唯一摆脱连接的方法是使套接字成为非阻塞的。如果是阻塞套接字,你就出不去了。

Is there any way that I can make connect function return after a time of my choice?

您的选择是将套接字标记为非阻塞。别无他法。阻塞意味着 'block' 在 socket.You 上发生事件之前执行线程不能根据您的需要阻塞套接字和超时。

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

Is there any way that I can make connect function return after a time of my choice?

向进程发送信号。

#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, ...);

  ...