我正在尝试在Powershell中编写一个例程,该例程将侦听UDP端口,然后在按下键时退出。我的问题是该程序仅在读取数据报后退出。
即它将读取n个值,用户将按F12键,程序将等待直到获得第n + 1个值,然后退出。
应该发生的是:读取n个值,用户将按F12键,程序应关闭。
$endpoint = New-Object System.Net.IPEndPoint ([IPAddress]::Any, $port)
$continue = $true
while($continue)
{
if ([console]::KeyAvailable)
{
echo "Exit with F12";
$x = [System.Console]::ReadKey()
switch ( $x.key)
{
F12 { $continue = $false }
}
}
else
{
$socket = New-Object System.Net.Sockets.UdpClient $port
$content = $socket.Receive([ref]$endpoint)
$socket.Close()
[Text.Encoding]::ASCII.GetString($content)
}
}
我对Powershell完全陌生,所以也许这是不可能的。其余代码已从此处的其他答案中窃取。
答案 0 :(得分:1)
使用ReceiveTimeout属性的解决方案,该属性在@bluuf的注释中提到:
$p = 17042
$e = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Any, $p)
$u = New-Object System.Net.Sockets.UdpClient $p
$u.Client.ReceiveTimeout = 100
try
{
for()
{
try
{
$b = $u.Receive([ref]$e)
$s = [System.Text.Encoding]::ASCII.GetString($b)
Write-Host $s
}
catch [System.Net.Sockets.SocketException]
{
if ( $_.Exception.SocketErrorCode -ne 'TimedOut' )
{
throw
}
}
if ( [System.Console]::KeyAvailable )
{
$x = [System.Console]::ReadKey($true)
if ( $x.key -eq [System.ConsoleKey]::F12 )
{
Write-Host 'Exit with F12'
break
}
}
}
}
finally
{
$u.Close()
}
异步版本可能看起来像这样:
if( -not('CallbackEventBridge' -as [type]) )
{
Add-Type @'
using System;
public sealed class CallbackEventBridge
{
public event AsyncCallback CallbackComplete = delegate { };
private CallbackEventBridge() {}
private void CallbackInternal(IAsyncResult result)
{
CallbackComplete(result);
}
public AsyncCallback Callback
{
get { return new AsyncCallback(CallbackInternal); }
}
public static CallbackEventBridge Create()
{
return new CallbackEventBridge();
}
}
'@
}
$sb = {
param($ar)
$e = $ar.AsyncState.e
$u = $ar.AsyncState.u
$b = $u.EndReceive($ar, [ref]$e)
$s = [System.Text.Encoding]::ASCII.GetString($b)
Write-Host $s
$ar.AsyncState.completed = $true
}
$bridge = [CallbackEventBridge]::Create()
Register-ObjectEvent -InputObject $bridge -EventName CallbackComplete -Action $sb > $null
$p = 17042
$e = New-Object System.Net.IPEndPoint ([System.Net.IPAddress]::Any, $p)
$u = New-Object System.Net.Sockets.UdpClient $p
$state = @{e = $e; u = $u; completed = $true}
try
{
for()
{
if( $state.completed )
{
$state.completed = $false
[void]$u.BeginReceive($bridge.Callback, $state)
}
if ( [System.Console]::KeyAvailable )
{
$x = [System.Console]::ReadKey($true)
if ( $x.key -eq [System.ConsoleKey]::F12 )
{
Write-Host 'Exit with F12'
break
}
}
[System.Threading.Thread]::Sleep(100)
}
}
finally
{
$u.Close()
}
在Oisin Grehan的PowerShell 2.0 – Asynchronous Callbacks from .NET文章中了解有关CallbackEventouBridge类的更多信息。
可以使用以下代码段测试这两个版本:
$p = 17042
$u = New-Object System.Net.Sockets.UdpClient
$b = [System.Text.Encoding]::ASCII.GetBytes('Is anybody there')
$u.Connect('localhost', $p)
[void]$u.Send($b, $b.Length)
$u.Close()