【问题标题】:Could someone show me an example of a custom timeout for the connect() function有人可以给我看一个 connect() 函数的自定义超时示例吗
【发布时间】:2016-05-01 00:25:02
【问题描述】:

我正在构建一个向服务器发送请求的应用程序,我需要实现一种方法来控制我尝试 connect() 到服务器的时间。

我想在十秒后结束 connect() 函数。我已经阅读了 select() 和非阻塞套接字,但我并不完全理解它是如何工作的。

谁能给我一个非常简单的例子来说明如何做到这一点?使用 C。谢谢。

另外,我还想为 send 和 recv 函数添加相同的超时。

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>  
#include <netinet/in.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include <errno.h>

int main(void) {

struct sockaddr_in server;
int sockfd;

sockfd = socket(AF_INET, SOCK_STREAM, 0);

server.sin_addr.s_addr = inet_addr("10.0.0.1");
server.sin_family = AF_INET;
server.sin_port = htons(atoi("80"));

fcntl(sockfd, F_SETFL, O_NONBLOCK);

struct timeval tv;
fd_set writefds;

tv.tv_sec = 5;
tv.tv_usec = 500000;

FD_ZERO(&writefds);
FD_SET(sockfd, &writefds);

connect(sockfd, (struct sockaddr *)&server, sizeof(server));

if (errno == EINPROGRESS)
{
        printf("In progress");
}

select(sockfd+1, NULL, &writefds, NULL, &tv);

你能解释一下为什么 errno 的 if 条件直到超时后才显示?这对我来说没有意义。是否有任何额外的代码我应该在这里查看以正确处理这个问题。谢谢。

【问题讨论】:

  • 除非先前的系统调用返回-1,否则测试errno 是不正确的。您需要以这种方式测试所有系统调用:socket(), fcntl(), connect(), select(), ...
  • 好的,谢谢。知道为什么在连接之前或之后的 printf 语句在超时成功之前不会打印。我只是对发生的事情感到困惑?
  • 因为fcntl()失败了,你没有检查错误,所以没有发现,所以socket仍然处于阻塞模式。当有人指出您的代码中存在重大故障时,“OK”并不是一个充分的回应。您应该更正并重新测试。
  • 让我尽快回复您一些更新的代码。另外,我不相信 fcntl 会失败,因为包含它时 connect 会立即退出。但我会看到的。
  • 我不会说没有错误检查被认为是我的代码中的一个主要缺陷,尽管它仍然是一个缺陷。为什么这里的人总是有聪明的说法?

标签: c sockets networking


【解决方案1】:

我不会写实际的代码,而是给你一个大纲。 (我假设是 Linux 或类似的东西。)

  1. 创建套接字。
  2. 在套接字 fd 上调用 fcntl 并设置 O_NONBLOCK 使套接字非阻塞的选项。 (你也可能是 可以通过在socket 上提供SOCK_NONBLOCK 选项来做到这一点 打电话。)
  3. 致电connect。它会立即返回。它将最 可能“失败”并出现错误EINPROGRESS,这意味着 连接操作正在进行中。
  4. 致电selectpoll等待 使套接字 fd 变为可写。这两个电话都有一个 超时选项。
  5. 如果套接字变为可写(即,您的 selectpoll 不会超时),通过调用检查连接状态 getsockopt 获取SO_ERROR 的值,这将表明 通过返回错误代码,connect 是成功还是失败 或 0 表示成功。

您也可以使用相同的技术来使sends 和recvs 超时(尽管对于接收,您需要等待套接字变为可读)。

有关详细信息,请参阅以下手册页:socket(2)、connect(2)、select(2)、poll(2)、socket(7)、getsockopt(2)。

【讨论】:

  • 您好,感谢您的回复。非常有帮助。我仍然无法完成所有事情,我已经用一些代码更新了我的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-02-27
相关资源
最近更新 更多