使用C

时间:2018-03-18 11:47:55

标签: c sockets tcp connect nonblocking

我目前正在研究套接字编程中的非阻塞I / O.在这个主题中,我遇到了一个概念,即可以将connect()视为非阻塞,即如果连接仍未建立,则会立即返回EINPROGRESS错误。同时连接已经建立,用户可以执行书中所述的其他任务,如下所示:

  

非阻塞连接有三种用途:

     
      
  1. 我们可以通过三次握手重叠其他处理。一个   connect需要一个RTT来完成(第2.6节),这可以   从局域网上的几毫秒到几百毫秒的任何地方   或者在WAN上几秒钟。我们可能还有其他处理方法   在这段时间内表演。

  2.   
  3. 我们可以使用它同时建立多个连接   技术。这已成为Web浏览器的流行,我们将展示   第16.5节中的一个例子。

  4.   
  5. 由于我们等待使用select建立连接,我们   可以指定select的时间限制,允许我们缩短   连接超时。许多实现都有超时   连接时间在75秒到几分钟之间。有   应用程序想要更短的超时,并使用一个   非阻塞连接是实现此目的的一种方法。

  6.   

我对本书中提到的支持相同的代码有疑问。代码如下:

 1 #include     "unp.h" // a header file containing all necessary files required to run this program   
 2 int
 3 connect_nonb(int sockfd, const SA *saptr, socklen_t salen, int nsec)
 4 {
 5     int     flags, n, error;
 6     socklen_t len;
 7     fd_set rset, wset;
 8     struct timeval tval;

 9     flags = Fcntl(sockfd, F_GETFL, 0);
10     Fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);

11     error = 0;
12     if ( (n = connect(sockfd, saptr, salen)) < 0)
13         if (errno != EINPROGRESS)
14             return (-1);

15     /* Do whatever we want while the connect is taking place. */

16     if (n == 0)
17         goto done;               /* connect completed immediately */

18     FD_ZERO(&rset);
19     FD_SET(sockfd, &rset);
20     wset = rset;
21     tval.tv_sec = nsec;
22     tval.tv_usec = 0;

23     if ( (n = Select(sockfd + 1, &rset, &wset, NULL,
24                     nsec ? &tval : NULL)) == 0) {
25         close(sockfd);          /* timeout */
26         errno = ETIMEDOUT;
27         return (-1);
28     }

29     if (FD_ISSET(sockfd, &rset) || FD_ISSET(sockfd, &wset)) {
30         len = sizeof(error);
31         if (getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len) < 0)
32             return (-1);     /* Solaris pending error */
33     } else
34         err_quit("select error: sockfd not set");

35   done:
36     Fcntl(sockfd, F_SETFL, flags);  /* restore file status flags */

37     if (error) {
38         close(sockfd);           /* just in case */
39         errno = error;
40         return (-1);
41     }
42     return (0);
43 }

上面的代码是套接字API支持的connect()实用程序的包装函数。这里我们将套接字设置为非阻塞。

怀疑是如果连接尚未建立,并且按照第15行,我们可以继续执行评论中提到的其他任务。但是不应该首先检查直接连接条件。因为没有检查我们继续进行的操作,所以在之前连接发生时需要花费时间。

如果我错了,请纠正我。

1 个答案:

答案 0 :(得分:1)

  

上面的第一点与下图中显示的内容相矛盾:

不,不是。 connect()与TCP SYN,SYN-ACK和ACK段有关。您的图像大约是recvfrom()和UDP数据报。没有矛盾,因为首先没有相互关联性。这个建议太荒谬了。

  

那是什么其他任务?

根据您的报价,驱动您首先使用非阻塞连接,例如,错误,另一个连接,这是正确的。

  

此外,它声明我们应该检查是否有客户端和服务器在同一台主机上的立即连接,然后根据这一点,不应该先进行检查,然后再继续。

是的,确实如此。

  

后一种情况显示在第16行。

是的,这就是检查的地方。你的问题?