2

特定のIPセットで匿名接続を受け入れるすべてのFTPサーバーを見つけようとしています。

基本的に、チェックしたい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;
}
4

2 に答える 2

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();
于 2013-03-17T03:10:21.640 に答える