我正在尝试找到所有在给定的ips上接受匿名连接的ftp服务器。
基本上,我得到了我要检查的IP,然后在每个IP上尝试一个ListDirectory。如果我没有例外,则ftp存在且可访问。
我正在使用异步方法来验证IP,这会使事情变得更快。但是,我需要等到所有异步调用都返回。为此,我对我所拥有的异步调用次数进行了计数,问题是此计数器永远不会达到0。
我的代码如下:
迭代IP:
static int waitingOn;
public static IEnumerable<Uri> GetFtps()
{
var result = new LinkedList<Uri>();
waitingOn = 0;
IPNetwork ipn = IPNetwork.Parse("192.168.72.0/21");
IPAddressCollection ips = IPNetwork.ListIPAddress(ipn);
foreach( var ip in ips )
{
VerifyFtpAsync(ip, result);
}
while (waitingOn > 0)
{
Console.WriteLine(waitingOn);
System.Threading.Thread.Sleep(1000);
}
return result;
}
并验证每个IP:
public async static void VerifyFtpAsync( IPAddress ip, LinkedList<Uri> ftps )
{
++waitingOn;
try
{
Uri serverUri = new Uri("ftp://" + ip);
FtpWebRequest request = (FtpWebRequest)WebRequest.Create(serverUri);
request.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
request.Timeout = 10000;
request.Credentials = new NetworkCredential("anonymous", "roim@search.com");
FtpWebResponse response = (FtpWebResponse) await request.GetResponseAsync();
// If we got this far, YAY!
ftps.AddLast(serverUri);
}
catch (WebException)
{
}
--waitingOn;
}
答案 0 :(得分:1)
首先,除非您正在编写事件处理程序,否则不应使用async void
。
接下来,如果async
方法可以并行运行(例如,如果此代码在控制台应用程序中运行),则需要保护变量和集合免受多线程访问的影响。在您的情况下,听起来您可能想要使用Task.WhenAll
而不是手动计数器,并删除共享集合。
public async static Task<Uri> VerifyFtpAsync(IPAddress ip)
{
try
{
...
return serverUri;
}
catch (WebException)
{
return null;
}
}
...
var ipTasks = ips.Select(ip => VerifyFtpAsync(ip));
var allResults = await Task.WhenAll(ipTasks);
var result = allResults.Where(url => url != null).ToArray();