退出UDP侦听例程

时间:2018-11-24 12:22:51

标签: powershell sockets

我正在尝试在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完全陌生,所以也许这是不可能的。其余代码已从此处的其他答案中窃取。

1 个答案:

答案 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()