【问题标题】:issue in non-blocking connect() with sockets in C [closed]在 C 中使用套接字的非阻塞 connect() 问题[关闭]
【发布时间】:2018-08-27 02:24:33
【问题描述】:

我目前正在学习套接字编程中的非阻塞 I/O。在本主题中,我遇到了可以将 connect() 设为非阻塞的概念,即如果连接仍未建立,它将立即返回 EINPROGRESS 错误。同时连接建立用户也可以执行书中所述的其他一些任务,如下所示:

非阻塞连接有三种用途:

  1. 我们可以将其他处理与三次握手重叠。一种 connect 需要一个 RTT 来完成(第 2.6 节),这可以是 从 LAN 上的几毫秒到数百毫秒 或在 WAN 上几秒钟。我们可能希望进行其他处理 在此期间执行。

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

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

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

 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 }

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

疑问是,如果连接尚未建立,根据第 15 行,我们可以继续执行评论中提到的其他任务。但是不应该首先检查直接连接条件。因为没有检查那个,我们继续做任何需要时间的事情,而之前可能会发生连接。

如果我错了,请纠正我。

【问题讨论】:

  • 发布Minimal, Complete, and Verifiable Example时,请不要添加行号。如果您想指出特定行,请在该行添加评论并在问题正文中告诉我们。
  • @Some 程序员老兄:我会编辑我的问题。
  • @Some 程序员老兄:现在请看问题。
  • 现在的问题和以前没有什么不同。您只是在问您自己的问题中已经回答的问题。这没有意义。否则你根本不理解第 16-17 行,尽管它们很琐碎。

标签: c sockets tcp connect nonblocking


【解决方案1】:

上面的第一点与下图所示矛盾:

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

其他任务是什么?

是什么促使您首先使用非阻塞连接,例如,err,另一个连接,根据您的报价。

此外,它指出如果客户端和服务器在同一台主机上,我们应该检查立即连接,那么根据这个,在继续之前不应该首先检查。

是的,确实如此。

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

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

【讨论】:

  • 好的,同意你的第一点。但是这段代码在检查连接建立时是否正确?
  • @POOJAGUPTA 你测试的时候发生了什么?
  • @EJP :我的问题是为什么在连接发生时它在评论中说做任何你想做的事情后检查它。直接连接应该是 else if 条件到第一个连接条件?
  • @Martin James:不,我没有测试过。我觉得这里使用的编程逻辑是不正确的。我的问题是为什么它在评论中说在连接发生时做任何你想做的事情后检查它。直接连接应该是 else if 条件到第一个连接条件?
  • @EJP :编辑了问题。请现在看看:)
猜你喜欢
  • 2010-12-30
  • 1970-01-01
  • 1970-01-01
  • 2012-05-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多