Absolutely the same feelings
Tag: Async
DNS collisions detection with F# Async Workflows
There is one more useful application of script from the “Explore local network with F# Async Workflows” post. During the check of the machine availability we can collect IP addresses of all machines. After that we can compare IPs of different host names for collision. It is a good way to understand what is going on in your network.
#r "System.DirectoryServices.dll" open System open System.Collections open System.DirectoryServices open System.Net.NetworkInformation open System.Threading.Tasks let hosts = use searcher = new DirectorySearcher(new DirectoryEntry(), Filter="(objectClass=computer)", PageSize=10000) (searcher.FindAll() :> IEnumerable) |> Seq.cast<SearchResult> |> Seq.map (fun x -> x.GetDirectoryEntry().Name) |> Seq.map (fun n -> n.Substring(n.IndexOf("=")+1)) |> Seq.toList let checkHosts hosts = let rec ping attempts (host:string) = async { let! pingResult = (new Ping()).SendPingAsync(host) |> Async.AwaitTask |> Async.Catch match pingResult with | Choice2Of2 e -> return None | Choice1Of2 reply when reply.Status = IPStatus.Success -> return Some(reply.Address.MapToIPv4().ToString()) | _ when attempts > 0 -> return! ping (attempts-1) host | _ -> return None } let results = hosts |> Seq.map (ping 4) |> Async.Parallel |> Async.RunSynchronously |> Seq.toList List.zip results hosts let dnsConflicts = hosts |> checkHosts |> List.filter (fst >> Option.isSome) |> Seq.groupBy fst |> Seq.filter (fun (_, seq) -> Seq.length seq > 1) |> Seq.map (fun (k, seq) -> (Option.get k, seq |> Seq.map snd |> Seq.toList) ) |> Seq.toList
Explore local network with F# Async Workflows
One more interesting task is to explore local network and check which computers are alive.
As a first step we need to get a list of computers which registered in Active Directory (as you understand, this approach works only for networks with Active Directory). Here we can use DirectorySearcher from System.DirectoryServices namespace. We create DirectoryEntry that by default points to the current domain and makes search over computers in this domain.
#r <System.DirectoryServices.dll> open System open System.Collections open System.DirectoryServices open System.Net.NetworkInformation open System.Threading.Tasks let hosts = use searcher = new DirectorySearcher(new DirectoryEntry(), Filter="(objectClass=computer)", PageSize=50000) (searcher.FindAll() :> IEnumerable) |> Seq.cast<SearchResult> |> Seq.map (fun x -> x.GetDirectoryEntry().Name) |> Seq.map (fun n -> n.Substring(n.IndexOf("=")+1)) |> Seq.toList
The next step is to check the availability of computers. F# Asynchronous Workflows help us here. We make a sequence of ping-calls(up to 4) to each computer which allows us to understand if computer is available or not. We are expecting to get a valid response with IPStatus.Success status. If we get an exception instead of response or run out of attempts, we will mark this computer as unavailable.
let checkHosts hosts = let rec ping attempts (host:string) = async { let! pingResult = (new Ping()).SendPingAsync(host) |> Async.AwaitTask |> Async.Catch match pingResult with | Choice2Of2 e -> return false | Choice1Of2 reply when reply.Status=IPStatus.Success -> return true | _ when attempts > 0 -> return! ping (attempts-1) host | _ -> return false } let results = hosts |> Seq.map (ping 4) |> Async.Parallel |> Async.RunSynchronously |> Seq.toList List.zip results hosts
Now we are ready to get a list of available computers.
let availableHosts = hosts |> checkHosts |> List.filter fst |> List.map snd
Play with your network and find something interesting :).