【问题标题】:Socket connection ends with Operation now in progress on non-blocking socket套接字连接以 Operation now in progress on non-blocking socket 结束
【发布时间】:2018-01-27 10:39:52
【问题描述】:

我在使用 connect() API 连接到目标 IP 时遇到问题。 connect() API 返回 -1 和 errno 作为 operation in progress

。我是否在建立连接之前过早地检查返回码?请看以下代码sn-p:

struct sockaddr_in      servAddr;
        servAddr.sin_family = AF_INET;
            servAddr.sin_port = htons(9190); 
        const char * remoteIp = 10.10.20.86;
            rc = inet_pton(AF_INET,remoteIp, &servAddr.sin_addr);
            if (rc == -1 || errno == EAFNOSUPPORT)
            {
                return 0;
            }
            rc = connect(fd, (sockaddr*)&servAddr, sizeof(servAddr));
         if ( rc < 0) // this is where it fails. rc is -1.
                   {
                        log("connect failure with [%s]",strerror(errno));
                        print_sock_connect_error();
                   }

我有两个问题:

  1. 目标 IP 和端口10.10.20.86:9190 正在等待连接,一旦接收到连接,它会将 ack 发送回源。我在 pcap 中看到了已建立的 tcp - ACK、SYN/ACK 和 ACK 到目的地 - 但仍然无法弄清楚为什么它返回 -1 时出错。那么我是在连接建立完成之前检查 rc 吗? sysctl net.ipv4.tcp_syn_retries 设置为 6。
  2. 上面的代码有问题吗?

【问题讨论】:

  • 请不要发送带有标签的垃圾邮件。即使问题可能同时适用于 C 和 C++,也只能使用您实际编程的语言的标签,因为这会影响可能的解决方案。
  • 在不相关的说明中,您检查来自inet_pton 的错误的条件存在缺陷。如果有错误,或者有 no 错误但 errno 恰好是 EAFNOSUPPORT,则返回 0。如果没有错误(即inet_pton 不返回-1),那么errno 的值是不确定的和未知的。那就别查了。

标签: c linux sockets tcp


【解决方案1】:

我是在连接建立完成之前检查 rc 吗?

是的,你是。连接建立期间的 TCP 乒乓并不是所有必须要做的。

上面的代码有什么问题吗?

嗯,是的,无论是它处理EINPROGRESS 情况的方式,还是使用非阻塞套接字进行连接。

来自connect()的Linux documentation

EINPROGRESS

套接字是非阻塞的,连接不能 立即完成。可以选择(2)或轮询(2) 通过选择要写入的套接字来完成。后 select(2) 表示可写,使用 getsockopt(2) 读取 SOL_SOCKET 级别的 SO_ERROR 选项,用于确定是否 connect() 成功完成(SO_ERROR 为零)或 不成功(SO_ERROR 是常见的错误代码之一 在这里列出,解释失败的原因)。

【讨论】:

    【解决方案2】:
    1. 10.10.20.86:9190 正在等待连接,一旦收到连接,它会将 ack 发送回源。我在 pcap 中看到建立的 tcp - ACK、SYN/ACK 和 ACK 到目的地 - 但仍然无法弄清楚为什么它返回 -1 并出错。那么我是在连接建立完成之前检查 rc 吗?

    你当然是。您正在立即检查它connect() 返回。由于您已将套接字置于非阻塞模式,因此三向线握手不可能在那时完成。

    sysctl net.ipv4.tcp_syn_retries 设置为 6。

    无关紧要。

    1. 上面的代码有什么问题吗?

    只是没有意义。

    • 如果您希望在connect() 返回之前连接完成或失败,请不要使用非阻塞模式。

    • 如果你想使用非阻塞模式,你必须使用select() 告诉你连接尝试何时完成。选择使套接字变为可写。 (这并不一定意味着它变为可写:这意味着连接尝试已完成,结果您可以通过getsockopt()/SO_ERROR 发现。)

    【讨论】:

      猜你喜欢
      • 2013-03-19
      • 2012-04-29
      • 1970-01-01
      • 2022-10-15
      • 2014-12-03
      • 2015-07-16
      • 1970-01-01
      • 2022-12-27
      • 2020-11-06
      相关资源
      最近更新 更多