【问题标题】:socket connect timeout in c using poll使用轮询的c中的套接字连接超时
【发布时间】:2011-11-22 17:21:23
【问题描述】:

我有一个使用阻塞 connect() 调用的现有多线程应用程序。

但是,我想为应用程序引入连接超时,如果服务器在 x 毫秒内没有响应我们的查询,应用程序将停止尝试并给出错误。

但是,我无法弄清楚如何使用民意调查来做到这一点。

@caf 的使用 select 的非阻塞连接非常有帮助。 但是与 poll 相比,我读到 select 的速度很慢,因此我想使用 poll。请告诉我这是不是真的?

我从the post这里粘贴他的代码

int main(int argc, char **argv) {
u_short port;                /* user specified port number */
char *addr;                  /* will be a pointer to the address */
struct sockaddr_in address;  /* the libc network address data structure */
short int sock = -1;         /* file descriptor for the network socket */
fd_set fdset;
struct timeval tv;

if (argc != 3) {
    fprintf(stderr, "Usage %s <port_num> <address>\n", argv[0]);
    return EXIT_FAILURE;
}

port = atoi(argv[1]);
addr = argv[2];

address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr(addr); /* assign the address */
address.sin_port = htons(port);            /* translate int2port num */

sock = socket(AF_INET, SOCK_STREAM, 0);
fcntl(sock, F_SETFL, O_NONBLOCK);

connect(sock, (struct sockaddr *)&address, sizeof(address));

FD_ZERO(&fdset);
FD_SET(sock, &fdset);
tv.tv_sec = 10;             /* 10 second timeout */
tv.tv_usec = 0;

if (select(sock + 1, NULL, &fdset, NULL, &tv) == 1)
{
    int so_error;
    socklen_t len = sizeof so_error;

    getsockopt(sock, SOL_SOCKET, SO_ERROR, &so_error, &len);

    if (so_error == 0) {
        printf("%s:%d is open\n", addr, port);
    }
}

close(sock);
return 0;

}

能否请您帮我使用 poll 编写类似的功能。

我在 RHEL 上并使用 gcc 4.5.x 版本。

更新:对于当前代码,一旦应用创建与服务器的连接,如何将套接字更改为阻塞模式。我无法找到取消设置此 O_NONBLOCK 的方法。 更新 2:fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) &amp; ~O_NONBLOCK); One post 指出我们可以使用上面的命令来做到这一点。但是没有登录。

【问题讨论】:

  • select 非常适合这个。
  • 我认为 poll 和 select 都很慢。 Check here.
  • 实际上,我需要同时构建solaris & linux complienet 代码。因此我不能选择 epoll()。需要接受民意调查或选择。
  • @AmeyJah 选择比 epoll 慢,而不是轮询,而且只有当您同时处理大量套接字时 - 只需使用 select。很好。
  • @gby 你能告诉我同时使用大量套接字会产生什么结果吗?选择会比轮询慢吗?

标签: c sockets asynchronous rhel


【解决方案1】:

select 不会比 poll 慢。但即使是这样,最小的差异也不太可能对您的应用程序产生影响。

要进行非阻塞超时连接,您可以从提供此类功能的现有应用程序中复制。 (例如,请参阅 here,了解如何操作)。

【讨论】:

  • 哦,抱歉,我看到你已经有使用 select 进行非阻塞连接的代码了。
【解决方案2】:

如果只有少数文件描述符被轮询,则 select() 和 poll() 相对于其他系统相关轮询 API 的性能是等效的。它们的扩展性都很差,但在程序只听几个 fd 时表现得很好。

其他特定于系统的轮询 API 的一个优点往往是它们将关联状态推送到内核中,因此每个轮询系统调用不需要从用户空间到内核空间的状态副本。只有少数事件,这种复制和扫描开销是微不足道的,而且这种好处不存在。

除非您需要扩展到处理数百或更多 fd,否则请坚持使用 select()。

如果您确实要处理许多 fd,并且您必须同时支持 Linux 和 Solaris,请考虑使用像 libeventlibev 这样的库来抽象出内核特定的高效等待 API。

【讨论】:

    猜你喜欢
    • 2011-02-05
    • 1970-01-01
    • 2012-10-11
    • 1970-01-01
    • 2018-11-29
    • 1970-01-01
    • 2011-05-11
    • 1970-01-01
    • 2014-07-05
    相关资源
    最近更新 更多