如何重新连接客户端到服务器?

8

我的服务器程序(套接字流)正在运行,它接受客户端。由于某些异常情况,服务器被终止。另一方的客户端正在等待服务器回复。 如何将正在运行的客户端重新连接到新的服务器? sockets中有哪些函数可��使用?


你想要将客户端连接到一个_新的_服务器吗?也就是说,如果服务器A启动了,客户端连接到了服务器A,服务器A宕机了,服务器B启动了,你希望客户端连接到服务器B? - Anish Ramaswamy
再次运行服务器 A - loganaayahee
你的程序总是在同一台机器上运行吗? - Anish Ramaswamy
一个服务器连接两个或更多客户端,然后服务器停止(不工作),客户端等待服务器的回复,我再次运行同样的服务器程序,连接到正在运行的客户端。 - loganaayahee
1
可能是在连接失败时重用套接字描述符的重复问题。 - alk
显示剩余2条评论
5个回答

13

connect() 连接过一次的套接字 不能 被再次使用 connect() 进行连接。

连接 TCP 服务器并读写数据的步骤如下(伪代码):

sd = socket(...) // create socket descriptor (allocate socket resource)
connect(sd, server-address, ...) // connect to server
read/write(sd, data)  // read from server 
close(sd) // close /socket descriptor (free socket resource)

如果在connect之后服务器出现问题,所有客户端能且应该做的就是:

在服务器恢复之前等待并重新尝试连接。

close(sd) // close socket descriptor (free socket resource)

并从头开始:

sd = socket(...) // create socket descriptor (allocate socket resource)
...

从头开始,以以下方式开始:

connect(sd, server-address, ...) // connect to server
...

可能会导致未定义的行为,但至少会产生错误。


0
int
connect_retry(int sockfd, const struct sockaddr *addr, socklen_t alen)
{
    int nsec;

    /*
     * Try to connect with exponential backoff.
     */

    for (nsec = 1; nsec <= MAXSLEEP; nsec <<= 1) {
        if (connect(sockfd, addr, alen) == 0) {

            /*
             * Connection accepted.
             */

            return(0);
        }

        /*
         * Delay before trying again.
         */

        if (nsec <= MAXSLEEP/2)
            sleep(nsec);
    }
    return(-1);
}

这是《UNIX环境高级编程》一书推荐的内容。

你也可以使用以下方法:

setsockopt()中的SO_REUSEADDR。它允许重用本地地址。


1
OP是不是在谈论这种情况:服务器在成功连接后崩溃了? - alk
这段代码不起作用。即使之前的连接尝试失败,也不能重新连接TCP套接字。您必须关闭它并创建一个新的。请勿在此处发布未经测试的代码技术。 - user207421

0

您连接到新服务器的方式与连接到原始服务器的方式相同。这方面没有不同的API。我不明白为什么您会有其他想法。


0

您无法在服务器上处理此问题,但可以为客户创建会话,当客户重新连接时,恢复其设置并继续发送和接收消息。在客户端应用程序中创建一个具有特定间隔的线程来检查服务器是否可用,并尝试重新连接过程,但我建议您检查一下服务器端程序,看看发生了什么导致您的程序崩溃?


0

首先,让我说一下任何事情都是可能的。有一个函数可以为您完成这项工作。它就是您可能已经用于TCP客户端的connect函数。您只需要考虑何时再次调用此连接即可。

那么现在什么时候使用connect函数呢?

让我提出一个可能的解决方案。

您需要一些监控软件(例如守护进程),以跟踪服务器进程的状态。它可以定期检查服务器进程是否处于活动状态。

考虑单个客户端和服务器的情况。客户端运行在A系统上;服务器运行在B系统上。

假设服务器在接收任何内容之前运行并崩溃。这意味着客户端已成功连接到服务器,但其send将失败。当send失败时,您可以联系位于B系统上的监控软件以了解发生了什么。

如果监视软件报告服务器没有发现任何问题,那么其他问题可能出现了(可能是中断、网络接口卡崩溃等),这些原因超出了本讨论的范围。
如果监视软件回复说它发现服务器程序已经停止运行,那么您可以:
  • 回复监视软件要求重新启动服务器
  • 或者告诉它自行关闭
  • 或者采取您认为合适的其他措施。
现在,在系统A中的客户端中,再次开始进行socketconnectsendrecv等过程。
实质上,您正在创建另一个服务器X,它负责您当前的服务器Y。当服务器Y停止运行时,您会寻找服务器X的原因。

服务器X到底能做什么,客户端不能做的呢?如果使用普通的读取超时来读取响应,而没有服务器X,会有什么问题吗? - user207421
不是说你不能这样做。权衡的是,如果该客户端死亡或被完全破坏,您需要处理它。此外,如果您的DevOps团队突然决定重新配置位于其他地方的另一台服务器,您会发布客户端更新吗(这可能会根据平台而产生成本)?每种情况都有取舍。 - Anish Ramaswamy
你正在把一个非常简单的情况复杂化了。每个编写的网络客户端都需要一个读取超时功能。在服务器X中,你不能编写神奇的代码:你只能编写本应该在客户端中的代码。读取超时是一行代码设置和一个捕获块检测。这非常基础。 - user207421
以一种轻蔑的口吻重复你之前的陈述并不能改变我的话。我并没有说你不能或不应该设置客户端读取超时。我只是在说我们两种解决方案都有权衡。我还明确指出,在我的第一段中,你可以简单地重新连接。 - Anish Ramaswamy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接