互联网中断时继续尝试与服务器通信
Posted
技术标签:
【中文标题】互联网中断时继续尝试与服务器通信【英文标题】:Keep trying to talk to server when the Internet is down 【发布时间】:2011-08-05 12:26:26 【问题描述】:所以我的应用程序正在与服务器交换请求/响应(没有问题),直到互联网连接中断几秒钟,然后回来。然后是这样的代码:
response = (HttpWebResponse)request.GetResponse();
将抛出异常,状态为ReceiveFailure
、ConnectFailure
、KeepAliveFailure
等。
现在,如果互联网连接恢复,我能够继续与服务器通信,这一点非常重要,否则我必须从头开始,这将需要很长时间。
当互联网恢复正常时,您将如何恢复这种通信?
目前,我一直在检查与服务器通信的可能性,直到有可能(至少在理论上)。我的代码尝试如下所示:
try
response = (HttpWebResponse)request.GetResponse();
catch (WebException ex)
// We have a problem receiving stuff from the server.
// We'll keep on trying for a while
if (ex.Status == WebExceptionStatus.ReceiveFailure ||
ex.Status == WebExceptionStatus.ConnectFailure ||
ex.Status == WebExceptionStatus.KeepAliveFailure)
bool stillNoInternet = true;
// keep trying to talk to the server
while (stillNoInternet)
try
response = (HttpWebResponse)request.GetResponse();
stillNoInternet = false;
catch
stillNoInternet = true;
但是,问题在于第二个 try-catch 语句即使在互联网恢复时也会不断抛出异常。
我做错了什么?有没有其他方法可以解决这个问题?
谢谢!
【问题讨论】:
不是您问题的答案,但如果您的连接中断很长时间,您目前没有真正的好方法来解决这个问题... 服务器也有5分钟的超时时间,所以如果连接真的掉线超过5分钟,那就这样杀了。 你为什么不设置一个定时器,每 10 分钟测试一次连接,然后重新启动它正在做的事情?或者也许每次发生连接失败时都会将等待时间增加一分钟。 【参考方案1】:您应该每次都重新创建请求,并且应该在循环中执行重试,并在每次重试之间等待。等待时间应随着每次失败而逐渐增加。
例如
ExecuteWithRetry (delegate
// retry the whole connection attempt each time
HttpWebRequest request = ...;
response = request.GetResponse();
...
);
private void ExecuteWithRetry (Action action)
// Use a maximum count, we don't want to loop forever
// Alternativly, you could use a time based limit (eg, try for up to 30 minutes)
const int maxRetries = 5;
bool done = false;
int attempts = 0;
while (!done)
attempts++;
try
action ();
done = true;
catch (WebException ex)
if (!IsRetryable (ex))
throw;
if (attempts >= maxRetries)
throw;
// Back-off and retry a bit later, don't just repeatedly hammer the connection
Thread.Sleep (SleepTime (attempts));
private int SleepTime (int retryCount)
// I just made these times up, chose correct values depending on your needs.
// Progressivly increase the wait time as the number of attempts increase.
switch (retryCount)
case 0: return 0;
case 1: return 1000;
case 2: return 5000;
case 3: return 10000;
default: return 30000;
private bool IsRetryable (WebException ex)
return
ex.Status == WebExceptionStatus.ReceiveFailure ||
ex.Status == WebExceptionStatus.ConnectFailure ||
ex.Status == WebExceptionStatus.KeepAliveFailure;
【讨论】:
【参考方案2】:我认为你想要做的是:
HttpWebResponse RetryGetResponse(HttpWebRequest request)
while (true)
try
return (HttpWebResponse)request.GetResponse();
catch (WebException ex)
if (ex.Status != WebExceptionStatus.ReceiveFailure &&
ex.Status != WebExceptionStatus.ConnectFailure &&
ex.Status != WebExceptionStatus.KeepAliveFailure)
throw;
当您想在失败时重试某事时,不要将其视为在某事失败时要执行的操作,而应将其视为循环直到成功。 (或您不想重试的失败)。以上将继续重试,直到返回响应或引发不同的异常。
引入某种最大重试限制也是一个好主意(例如,在 1 小时后停止重试)。
【讨论】:
【参考方案3】:如果在您恢复连接时它仍在执行此操作 - 那么我的猜测是它只是再次返回相同的结果。
您可能想尝试每次重新创建请求,但我认为代码或逻辑没有太大问题。除了你永远阻止这个线程的事实。但是,如果这本身就是一个工作线程,那可能没问题。
【讨论】:
以上是关于互联网中断时继续尝试与服务器通信的主要内容,如果未能解决你的问题,请参考以下文章
使用 SwiftUI @Binding 预览崩溃:与应用程序的通信中断