套接字连接以非阻塞套接字上正在进行的操作结束

时间:2018-01-27 10:39:52

标签: c linux sockets tcp

使用 connect() API连接到目标IP时遇到问题。 connect() API会将-1和错误号码返回为operation in progress

。我是否在建立连接之前过早检查返回代码?请参阅以下代码段:

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发送回源。我看到tcp建立了 - ACK,SYN / ACK和ACK到目的地 - 在 pcap 中,但仍然无法弄清楚为什么它返回-1有错误。那么我是否在连接建立完成之前检查了rc? sysctl net.ipv4.tcp_syn_retries设为6.
  2. 上面的代码有什么问题吗?

2 个答案:

答案 0 :(得分:1)

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

你当然是。您立即connect()返回检查它。当你将套接字置于非阻塞模式时,那时三路线握手就不可能完成了。

  

sysctl net.ipv4.tcp_syn_retries设置为6.

不相关。

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

只是它没有意义。

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

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

答案 1 :(得分:0)

  

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

是的,你是。连接设置期间的TCP乒乓不是必须完成的。

  

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

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

来自connect()的Linux documentation

  

<强> EINPROGRESS

     

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