如何在 SocketException 后重新启动网络流
How to restart a Network Stream after a SocketException
我有一段代码可以从 public 互联网上的服务器读取 JSON 流。我试图通过捕获异常并尝试在给定的时间间隔内重新启动它来使连接更加稳健,但我一直无法弄清楚如何重新启动它。
我的推流代码如下
TcpClient connection = new TcpClient(hostname, port);
NetworkStream stream = connection.GetStream();
thread = new Thread(ProcessStream);
thread.Start(stream);
我的 ProcessStream 方法是
private void ProcessStream(object stream)
{
Stream source = (NetworkStream)stream;
byte[] line;
int count;
const int capacity = 300;
ReadState readState;
while ((readState = ReadStreamLine(source, out line, out count, capacity)) != ReadState.EOF && _stopFeed == false)
{
if (readState != ReadState.Error && count > 4)
{
byte[] line1 = new byte[count];
Array.Copy(line, line1, count);
Process(line1); // return ignored in stream mode
}
else
{
ReadFail(line, count);
}
}
}
我的 ReadStream 函数获取流 s,执行 s.ReadByte,然后在网络连接断开时捕获异常。正是在这里,我不确定如何尝试定时重启流。网络恢复后不会自动重启
您可能首先将您的流添加到 运行 流的静态列表中,并在完成阅读后将其从那里删除。
记得使用锁定!
然后在 NetworkGone-Catch 中,您可以将您的列表复制到 "todoAfterNetworkIsUpAgain"-List 并启动一个计时器来检查网络,并在您的网络再次启动后重新开始读取流。
那是不可能的。这就像你在 phone 上给你的朋友打电话,他在谈话中挂断了电话。无论你等多久,你都不会再听到他的消息。您所能做的就是挂断 phone 并重新拨这个号码。除非服务器支持可重启下载(使用 HttpWebRequest.AddRange),否则您将不得不从头开始重新下载 json。
如果这种情况经常发生,那么这不能用服务器离线或过载来解释,请记住,服务器很可能是故意这样做的。通常是因为您超出了某种配额。与服务器所有者交谈,他们通常有一个付费计划,让您可以使用更多资源。
据我所知,您在开始您的方法之前实例化了您的 TcpClient
。因此,为了重新启动您的流,您需要在重试之前重新实例化或重新初始化您的连接流。
try
{
// Do something
}
catch (Exception ex)
{
// Caught your exception, might be ideal to log it too
// Have a count, if count is less than goal
// Call your method again
if (count < 5)
{
// re-initialize or re-instantiate connection
TcpClient connection = new TcpClient(host, port);
NetworkStream stream = connection.GetStream();
ProcessStream(stream);
}
}
希望对您有所帮助。
这可能看起来有点凝灰岩,但事实并非如此。
以更好的方式使用递归和线程,您的问题可能会得到解决
对于递归
http://www.dotnetperls.com/recursion
线程
查看 msdn 文档或从 albahari
获取概念
我有一段代码可以从 public 互联网上的服务器读取 JSON 流。我试图通过捕获异常并尝试在给定的时间间隔内重新启动它来使连接更加稳健,但我一直无法弄清楚如何重新启动它。
我的推流代码如下
TcpClient connection = new TcpClient(hostname, port);
NetworkStream stream = connection.GetStream();
thread = new Thread(ProcessStream);
thread.Start(stream);
我的 ProcessStream 方法是
private void ProcessStream(object stream)
{
Stream source = (NetworkStream)stream;
byte[] line;
int count;
const int capacity = 300;
ReadState readState;
while ((readState = ReadStreamLine(source, out line, out count, capacity)) != ReadState.EOF && _stopFeed == false)
{
if (readState != ReadState.Error && count > 4)
{
byte[] line1 = new byte[count];
Array.Copy(line, line1, count);
Process(line1); // return ignored in stream mode
}
else
{
ReadFail(line, count);
}
}
}
我的 ReadStream 函数获取流 s,执行 s.ReadByte,然后在网络连接断开时捕获异常。正是在这里,我不确定如何尝试定时重启流。网络恢复后不会自动重启
您可能首先将您的流添加到 运行 流的静态列表中,并在完成阅读后将其从那里删除。 记得使用锁定!
然后在 NetworkGone-Catch 中,您可以将您的列表复制到 "todoAfterNetworkIsUpAgain"-List 并启动一个计时器来检查网络,并在您的网络再次启动后重新开始读取流。
那是不可能的。这就像你在 phone 上给你的朋友打电话,他在谈话中挂断了电话。无论你等多久,你都不会再听到他的消息。您所能做的就是挂断 phone 并重新拨这个号码。除非服务器支持可重启下载(使用 HttpWebRequest.AddRange),否则您将不得不从头开始重新下载 json。
如果这种情况经常发生,那么这不能用服务器离线或过载来解释,请记住,服务器很可能是故意这样做的。通常是因为您超出了某种配额。与服务器所有者交谈,他们通常有一个付费计划,让您可以使用更多资源。
据我所知,您在开始您的方法之前实例化了您的 TcpClient
。因此,为了重新启动您的流,您需要在重试之前重新实例化或重新初始化您的连接流。
try
{
// Do something
}
catch (Exception ex)
{
// Caught your exception, might be ideal to log it too
// Have a count, if count is less than goal
// Call your method again
if (count < 5)
{
// re-initialize or re-instantiate connection
TcpClient connection = new TcpClient(host, port);
NetworkStream stream = connection.GetStream();
ProcessStream(stream);
}
}
希望对您有所帮助。
这可能看起来有点凝灰岩,但事实并非如此。
以更好的方式使用递归和线程,您的问题可能会得到解决
对于递归
http://www.dotnetperls.com/recursion
线程
查看 msdn 文档或从 albahari