运行PowerShell UDP端口测试脚本报错:UdpClient无BeginConnect方法
解决UDP端口测试脚本中
System.Net.Sockets.UdpClient的方法不存在问题 问题背景
运行基于System.Net.Sockets.UdpClient的PowerShell UDP端口测试脚本时,触发以下错误:
Method invocation failed because [System.Net.Sockets.UdpClient] does not contain a method named 'BeginConnect'. At line:12 char:9 + $connect = $obj.BeginConnect($target,$port,$null,$null) + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : InvalidOperation: (:) [], RuntimeException + FullyQualifiedErrorId : MethodNotFound
原始脚本
$targetservers = "192.168.2.2" $ports = "53" $result = @() foreach ($target in $targetservers) { foreach ($port in $ports) { $obj = new-Object System.Net.Sockets.UdpClient $connect = $obj.BeginConnect($target,$port,$null,$null) $Wait = $connect.AsyncWaitHandle.WaitOne(100,$false) If (-Not $Wait) { write-host $target ‘port’ $port ‘Closed – Timeout’ } else { $value = “Open” write-host $target ‘port’ $port $value $r = new-object -type psobject $r | add-member -membertype noteproperty -name host -value $target $r | add-member -membertype noteproperty -name port -value $port $r | add-member -membertype noteproperty -name state -value $value $result += $r } } }
UPDATE 1脚本
$targetservers = "192.168.200.11" $ports = "53" $result = @() foreach ($target in $targetservers) { foreach ($port in $ports) { $obj = new-Object System.Net.Sockets.UdpClient $connect = $obj.Connect($target,$port) $Wait = $connect.AsyncWaitHandle.WaitOne(100,$false) If (-Not $Wait) { write-host $target ‘port’ $port ‘Closed – Timeout’ } else { $value = “Open” write-host $target ‘port’ $port $value $r = new-object -type psobject $r | add-member -membertype noteproperty -name host -value $target $r | add-member -membertype noteproperty -name port -value $port $r | add-member -membertype noteproperty -name state -value $value $result += $r } } }
问题根源
UdpClient类没有BeginConnect方法:这个异步方法属于TCP协议的TcpClient,UDP是无连接协议,不存在“建立连接”的概念。- UPDATE 1脚本的错误:
UdpClient.Connect()是无返回值的void方法,执行后$connect为$null,调用$connect.AsyncWaitHandle会直接报错。而且Connect()只是设置后续发送/接收的默认远程端点,不会发起任何实际的网络请求,根本无法用来判断端口状态。
正确解决方案
UDP端口测试的核心是发送测试数据包并等待响应,因为UDP没有连接握手,只能通过目标是否返回响应来判断端口是否开放(或服务是否存活)。以下是修正后的脚本(以DNS服务为例):
$targetservers = "192.168.2.2" $ports = "53" $result = @() foreach ($target in $targetservers) { foreach ($port in $ports) { $state = "Closed/Unresponsive" $udpClient = $null try { $udpClient = New-Object System.Net.Sockets.UdpClient # 设置发送和接收超时(单位:毫秒) $udpClient.Client.ReceiveTimeout = 1000 $udpClient.Client.SendTimeout = 1000 # 发送符合DNS协议的测试查询包(查询www.example.com的A记录) $dnsTestPacket = [byte[]]@( 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x77, 0x77, 0x77, 0x07, 0x65, 0x78, 0x61, 0x6D, 0x70, 0x6C, 0x65, 0x03, 0x63, 0x6F, 0x6D, 0x00, 0x00, 0x01, 0x00, 0x01 ) $udpClient.Send($dnsTestPacket, $dnsTestPacket.Length, $target, $port) | Out-Null # 尝试接收响应 $remoteEndpoint = New-Object System.Net.IPEndPoint([System.Net.IPAddress]::Any, 0) $response = $udpClient.Receive([ref]$remoteEndpoint) if ($response -ne $null) { $state = "Open/Responsive" } } catch [System.Net.Sockets.SocketException] { # 根据错误码区分不同情况 switch ($_.Exception.ErrorCode) { 10060 { $state = "Closed – Timeout" } 10049 { $state = "Target Unreachable" } default { $state = "Error: $($_.Exception.Message)" } } } finally { # 确保释放资源 if ($udpClient) { $udpClient.Close() } } Write-Host "$target port $port $state" # 添加结果到集合 $result += [PSCustomObject]@{ Host = $target Port = $port State = $state } } } # 输出最终结果 $result
脚本关键说明
- 协议适配:测试不同UDP服务时,需要发送对应协议的测试包(比如SNMP用GetRequest包),否则目标服务可能不会返回响应。
- 超时控制:通过
ReceiveTimeout和SendTimeout避免脚本长时间等待。 - 异常处理:捕获
SocketException来处理超时、不可达等网络异常,更准确判断端口状态。
内容的提问来源于stack exchange,提问作者Arbelac
相关产品推荐
相关产品推荐

