- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
我们有一个(长期运行的)Windows 服务,除其他外,它使用 FtpWebRequest 定期与嵌入在第三方设备上的 FTP 服务器通信。这在大多数情况下都很好用,但有时我们的服务会停止与设备通信,但只要您重新启动我们的服务,一切都会重新开始。
我花了一些时间使用 MCVE(包括在下面)对此进行调试,并通过 Wireshark 发现一旦通信开始失败,就没有网络流量流向外部 FTP 服务器(根本没有数据包显示流向该 IP Wireshark )。如果我尝试从同一台机器上的另一个应用程序(如 Windows 资源管理器)连接到同一个 FTP,一切正常。
在一切停止工作之前查看数据包,我看到来自设备的设置了重置 (RST) 标志的数据包,所以我怀疑这可能是问题所在。一旦我们运行的服务在计算机上的网络堆栈的某个部分接收到重置数据包,它就会执行 this article 的 TCP 重置部分中描述的操作,并阻止从我们的进程到设备的所有进一步通信。
据我所知,我们与设备通信的方式没有任何问题,而且大多数情况下,完全相同的代码也能正常工作。重现该问题的最简单方法(请参阅下面的 MCVE)似乎是同时与 FTP 建立大量单独的连接,因此我怀疑当与 FTP 建立大量连接时可能会出现该问题(不是全部由我们)同时进行。
问题是,如果我们重启进程,一切正常,我们确实需要重新建立与设备的通信。有没有办法重新建立通信(经过适当的时间后)而不必重新启动整个过程?
不幸的是,FTP 服务器嵌入在一个相当老旧的第三方设备上运行,该设备不太可能更新以解决此问题,即使更新了我们仍然希望/需要与所有已经存在的设备进行通信如果可能,无需我们的客户更新字段。
我们知道的选项:
使用命令行 FTP 客户端,例如 Windows 中内置的客户端。
创建另一个应用程序来处理我们在每个请求完成后拆除的 FTP 通信部分。
这在 LINQPad 中运行并相当可靠地重现了问题。通常前几个任务成功,然后问题出现,之后所有任务开始超时。在 Wireshark 中,我可以看到我的计算机和设备之间没有发生任何通信。
如果我再次运行该脚本,则所有 任务都会失败,直到我重新启动 LINQPad 或执行“取消所有线程并重置”以重新启动 LINQPad 用于运行查询的进程。如果我做了其中任何一件事情,那么我们就会回到前几项成功的任务。
async Task Main() {
var tasks = new List<Task>();
var numberOfBatches = 3;
var numberOfTasksPerBatch = 10;
foreach (var batchNumber in Enumerable.Range(1, numberOfBatches)) {
$"Starting tasks in batch {batchNumber}".Dump();
tasks.AddRange(Enumerable.Range(1, numberOfTasksPerBatch).Select(taskNumber => Connect(batchNumber, taskNumber)));
await Task.Delay(TimeSpan.FromSeconds(5));
}
await Task.WhenAll(tasks);
}
async Task Connect(int batchNumber, int taskNumber) {
try {
var client = new FtpClient();
var result = await client.GetFileAsync(new Uri("ftp://192.168.0.191/logging/20140620.csv"), TimeSpan.FromSeconds(10));
result.Count.Dump($"Task {taskNumber} in batch {batchNumber} succeeded");
} catch (Exception e) {
e.Dump($"Task {taskNumber} in batch {batchNumber} failed");
}
}
public class FtpClient {
public virtual async Task<ImmutableList<Byte>> GetFileAsync(Uri fileUri, TimeSpan timeout) {
if (fileUri == null) {
throw new ArgumentNullException(nameof(fileUri));
}
FtpWebRequest ftpWebRequest = (FtpWebRequest)WebRequest.Create(fileUri);
ftpWebRequest.Method = WebRequestMethods.Ftp.DownloadFile;
ftpWebRequest.UseBinary = true;
ftpWebRequest.KeepAlive = false;
using (var source = new CancellationTokenSource(timeout)) {
try {
using (var response = (FtpWebResponse)await ftpWebRequest.GetResponseAsync()
.WithWaitCancellation(source.Token)) {
using (Stream ftpStream = response.GetResponseStream()) {
if (ftpStream == null) {
throw new InvalidOperationException("No response stream");
}
using (var dataStream = new MemoryStream()) {
await ftpStream.CopyToAsync(dataStream, 4096, source.Token)
.WithWaitCancellation(source.Token);
return dataStream.ToArray().ToImmutableList();
}
}
}
} catch (OperationCanceledException) {
throw new WebException(
String.Format("Operation timed out after {0} seconds.", timeout.TotalSeconds),
WebExceptionStatus.Timeout);
} finally {
ftpWebRequest.Abort();
}
}
}
}
public static class TaskCancellationExtensions {
/// http://stackoverflow.com/a/14524565/1512
public static async Task<T> WithWaitCancellation<T>(
this Task<T> task,
CancellationToken cancellationToken) {
// The task completion source.
var tcs = new TaskCompletionSource<Boolean>();
// Register with the cancellation token.
using (cancellationToken.Register(
s => ((TaskCompletionSource<Boolean>)s).TrySetResult(true),
tcs)) {
// If the task waited on is the cancellation token...
if (task != await Task.WhenAny(task, tcs.Task)) {
throw new OperationCanceledException(cancellationToken);
}
}
// Wait for one or the other to complete.
return await task;
}
/// http://stackoverflow.com/a/14524565/1512
public static async Task WithWaitCancellation(
this Task task,
CancellationToken cancellationToken) {
// The task completion source.
var tcs = new TaskCompletionSource<Boolean>();
// Register with the cancellation token.
using (cancellationToken.Register(
s => ((TaskCompletionSource<Boolean>)s).TrySetResult(true),
tcs)) {
// If the task waited on is the cancellation token...
if (task != await Task.WhenAny(task, tcs.Task)) {
throw new OperationCanceledException(cancellationToken);
}
}
// Wait for one or the other to complete.
await task;
}
}
最佳答案
这让我想起了旧的(?)IE 行为,即使在 N 次不成功的尝试后网络恢复时也不会重新加载页面。
您应该尝试将 FtpWebRequest
的缓存策略设置为 BypassCache
。
HttpRequestCachePolicy bypassPolicy = new HttpRequestCachePolicy(
HttpRequestCacheLevel.BypassCache
);
ftpWebRequest.CachePolicy = bypassPolicy;
设置KeepAlive
后。
关于c# - 如何在不重新启动进程的情况下重新启动与发回重置数据包的 FTP 服务器的通信?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33044415/
使用 Python 的 rtmplib 绑定(bind)并遇到一些问题。 首先, 我有这样的东西: import librtmp conn = librtmp.RTMP(...) conn.con
基本上,我是在查看 Motorstorm 排行榜时在 PS3 上窃听数据包。排行榜以 XML 格式发送到我的 ps3,但只有在我获得授权后。那么有人可以告诉我这三个数据包之间发生了什么,以及我如何在浏
我正在努力了解 TCP,但解析大量 RFC 并没有帮助。我相信我了解连接和关闭握手,但我似乎无法找到任何总结实际数据流的内容。 在连接和关闭握手之间 TCP 数据包看起来像什么? (特别是标题) 最佳
我正在尝试通过 RCON 端口与我的 Minecraft 服务器通信。 虽然我不知道如何使用套接字和流的东西。四处寻找,我发现他们都有一些共同点。套接字、输入流和输出流。 我在我的代码中试过了,但返回
我正在 UDP 之上设计一个简单的协议(protocol),现在我意识到其他人可以将数据包发送到我正在监听的端口。这样的数据包对于我的应用程序来说显然是不正确的(我现在不担心安全问题) 是否有过滤这些
我目前有一个具有可自定义滴答率的游戏服务器,但在本示例中,我们建议服务器每秒仅滴答一次或 1hz。我想知道如果客户端发送速率比服务器快,因为我当前的设置似乎不起作用,那么处理传入数据包的最佳方法是什么
我无法理解网络字节顺序以及通过 UDP 发送和接收数据的顺序。我正在使用 C#。 我有一个结构保持: message.start_id = 0x7777CCCC; message.me
我正在为 USB 设备编写代码。假设 USB 主机开始控制读取传输以从设备读取一些数据,并且请求的数据量(设置数据包中的 wLength)是端点 0 最大数据包大小的倍数。那么在主机接收到所有数据后(
我有一台 Windows PC、Marvell 交换机、Netgear 交换机和一台 Ubuntu 机器连接在一起(通过 Netgear 交换机)。 我最近从 Windows PC 向 Marvell
在查看数据包字节码时,您将如何识别 dns 数据包。 IP header 的协议(protocol)字段会告诉后面有一个 UDP 帧,但是在 UDP 帧内没有协议(protocol)字段来指定接下来会
我有一个通过 udf 的 802.11 (wifi) 上各种类型的流量的 pcap。由于 MTU,udp(或更准确地说是 IP)对 wifi 数据包进行分段。我目前正在使用 SharpPcap 读取并
我正在开发的 Core Audio 应用程序上有此崩溃日志。我目前正在调试它,所以我的问题不是关于崩溃本身,而是关于 的含义“k”包 . 这是什么意思 ? 我已阅读 this , 和 this (关于
我在一台 VM Ubuntu 16.04 机器上的 100 个多播组上生成 UDP 数据包,并在另一台 VM Ubuntu 16.04 机器上订阅这些组。两者都在由 Hyper-V 管理器运行的 HP
这个问题在这里已经有了答案: How can I fix 'android.os.NetworkOnMainThreadException'? (66 个回答) 6年前关闭。 我正在尝试创建一个简单的
我正在寻找使用 Java 来欺骗 UDP 数据包。是否有任何好的 Java 库可以让您创建自己的 RAW SOCKETS? 最佳答案 我会使用包装 libpcap 的 Java API . libpc
我在基于 Tyrus 的客户端和 tomcat Web 服务器之间使用没有压缩的 websocket。我在 tomcat 端看到消息传入和传出我的套接字,但如果我设置一个wireshark来观察它们传
我的应用程序在模拟器中运行时无法接收 UDP 数据包。 UDP 数据包由“localhost”上的以下 java 程序通过端口 49999 发送。 DatagramSocket clien
我正在开发一个 Google Glass 应用程序,它需要在工作线程中监听 UDP 数据包(与发送 UDP 数据包的现有系统集成)。我之前发布了一个问题(请参阅 here )并收到了一个答案,其中提供
我正在从客户端向服务器发送两个数据包。我遇到的问题是,在服务器上读取的数据使两个字符串对于发送的最长字符串具有相同的长度。例如: 如果字符串 1 为:1234 字符串 2 为:abcdefghi 服务
我知道这是不好的做法,但是可以执行以下操作吗? Send packet1 to UDP port 1 port 1 receives packet1 and sends it to port 2 po
我是一名优秀的程序员,十分优秀!