因此,我有一个尝试与服务器连接的客户端。 ip和端口从配置文件中检索。如果配置文件中的某些内容不正确,我需要程序顺利失败。我使用以下代码连接到服务器
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1)
{
perror("client: connect");
close(sockfd);
continue;
}
如果用户尝试连接到不接受连接(即不存在)的子网上的服务器,则程序将失败,并显示No route to host
。如果程序尝试连接到不在子网上的服务器(即配置错误),则程序会在connect()
调用处挂起。我做错了什么?我需要这样做是为了向用户提供有关应用程序失败的反馈。
答案 0 :(得分:3)
您没有做错任何事情。 TCP是为面对网络问题而设计的可靠性,因此,如果它没有收到对其初始连接请求的响应,则它会重试几次,以防请求或响应在网络中丢失。 Linux上的默认参数导致大约需要一分钟时间才能放弃。然后它将报告失败,并显示 docker run -d --hostname my-rabbit -p 5672:5672 --name some-rabbit rabbitmq:3
错误。
如果您想更快地检测到故障,请参阅C: socket connection timeout
答案 1 :(得分:1)
通常,我们不会在continue
语句中使用if
,除非if
语句在循环中(您未显示)。假设存在外部循环,则这将负责接下来发生的事情..要么继续重新进入if
块(以尝试再次连接),要么跳过它。
请注意,您正在sockfd
块内关闭if
,因此,如果您的循环重新进入if
块以进行重试,则它需要首先创建一个新的套接字。
我建议阅读一些客户端和服务器端套接字连接的示例代码,以更好地了解其工作原理http://www.cs.rpi.edu/~moorthy/Courses/os98/Pgms/socket.html
如果所有操作均失败,请在if
块周围提供代码,并说明您希望“顺利失败”的方式。一种“突然”失败的方法是将continue
语句换成对exit()
“-)的调用
编辑:在阅读Barmar的答案和他的评论后,您还需要注意以下几点:
如果发起套接字是连接模式,则connect()应该 尝试建立与该地址指定的地址的连接 地址参数。如果无法立即建立连接 并且未为套接字的文件描述符设置O_NONBLOCK, connect()最多应阻止一个未指定的超时间隔,直到 连接已建立。如果超时时间间隔在 建立连接后,connect()将失败并且连接 尝试应中止。
还..
如果无法立即建立连接并且O_NONBLOCK为 为套接字的文件描述符设置时,connect()将失败,并且 将errno设置为[EINPROGRESS],但连接请求不得为 终止,并且连接应异步建立。 随后在同一套接字之前调用connect() 建立连接,将失败并将errno设置为[EALREADY]
当您说“程序挂起”时,您的意思是永久的,或者是一段可能由TCP / IP超时解释的时期。
如果这和Barmar的答案仍然不够,那么将有助于根据建议查看周围的代码,并确定是被阻止还是未被阻止等。