监听多个组播端口

Listen on multiple multicast ports

在我们的 phone 系统上,我们使用多播进行寻呼。偶尔有人会不小心按下按钮,我们必须启动 Wireshark 来追踪 whodunit。所以我构建了一个 Powershell 脚本来侦听新的多播数据包并记录它们。很好用,但我只能绑定一个端口。

我试过使用 Start-Job 和工作流程,但没有成功。不过,这完全可以由我来承担。那么...关于如何在多个端口上进行侦听的想法?

$outfile = "c:\multicast log\multicast.txt"

function StartListener{
    Param(
        [Parameter(Mandatory)]
        $IPAddress,
        [Parameter(Mandatory)]
        $Port
    )

    $client = New-Object System.Net.Sockets.UDPClient
    $client.ExclusiveAddressUse = $false;
    #$localEp = [System.Net.IPEndPoint]::New([IPAddress]::Any, $Port);
    $localEp = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Any, $port)
    $remEP = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any,0)

    $client.Client.SetSocketOption([System.Net.Sockets.SocketOptionLevel]::Socket, [System.Net.Sockets.SocketOptionName]::ReuseAddress, $true);
    $client.ExclusiveAddressUse = $false;

    $client.Client.Bind($localEp);
    $multicastaddress = [IPAddress]::Parse($IpAddress);
    $client.JoinMulticastGroup($multicastaddress);

    Write-Host "Listening. This will never quit so you will need to force close it"

    $NewStream = $true
    $last_remEP = ""
    #initialize last_now to something that won't interfere
    $last_now = (Get-Date).AddYears(-1)
    while ($true) {
        $receivedbytes = $client.Receive([ref]$remEP);
        $now = Get-Date
        $cur_remEP = $($remEP.ToString())
        if ($last_remEP -eq $cur_remEP) {
            if ($now -gt ($last_now).AddSeconds(1)) {
                $NewStream = $true
            } else {
                $NewStream = $false
            }
        } else {
            $NewStream = $true
        }
        if ($NewStream) {
            $last_remEP = $cur_remEP
            if ((type $outfile).Count -ge 100) {
                (Get-Content $outfile | Select-Object -Skip 25) | Set-Content $outfile
            }
            Add-Content $outfile "$($now.ToString("yyyy-MM-dd hh:mm:ss tt")) - Received multicast from $cur_remEP"
        }
        $last_now = $now
    }
}

Clear-Content $outfile
$now = Get-Date -Format "yyyy-MM-dd hh:mm:ss tt"
Add-Content $outfile "$now - multicast logging started"

startlistener 224.0.1.75 50008
startlistener 224.0.1.75 50009

pause

您应该能够 运行 不同端口上的侦听器作为作业。但是,您不应该让作业写入同一个文件,因为这可能会导致并发写入尝试。更好的方法是让作业写入 STDOUT 并让您的启动器定期从作业中获取输出并将其写入文件:

$addr  = '224.0.1.75'
$ports = ...
$sb = {
    Param(
        [Parameter(Mandatory=$true)]
        [Net.IPAddress]$IPAddress,
        [Parameter(Mandatory=$true)]
        [int]$Port
    )

    $client = New-Object Net.Sockets.UDPClient
    ...
}

$jobs = foreach ($port in $ports) {
    Start-Job -Name "${addr}:${port}" -ScriptBlock $sb -ArgumentList $addr, $port
}

while ($true) {
    $jobs | ForEach-Object {
        $output = Receive-Job -Id $_.Id
        if ($output) {
            "{0}`t{1}" -f $_.Name, $output | Add-Content $outfile
        }
    }
    Start-Sleep -Milliseconds 500
}

话虽如此,WinDump 跟踪这些数据包并轮换捕获文件不是更容易吗?