You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Blazor WebAssembly中使用Ping类执行设备Ping操作的问题排查

在Blazor WebAssembly中无法直接使用Ping类执行Ping操作的原因及解决办法

首先直接给结论:你没办法在Blazor WebAssembly的浏览器环境里直接用System.Net.NetworkInformation.Ping实现Ping操作,这是浏览器的安全限制导致的。

为什么你的代码会静默失败?

浏览器出于安全考虑,完全禁止前端代码直接发送ICMP协议包(Ping操作依赖的就是ICMP),而Ping.Send方法本质是调用系统底层的ICMP能力,在WASM的浏览器沙箱里这个API根本无法正常工作——甚至在你调用Send之前,可能创建Ping实例或者执行相关操作时就已经抛出了异常,但你的代码里catch块吞了所有异常,没有任何日志或提示,所以看起来程序“直接结束”,没有执行后续逻辑。

可行的替代方案

既然前端做不了,那就换个思路,通过后端中转来实现:

1. 后端API中转(推荐)

在你的ASP.NET Core后端(如果有的话)写一个接口,让服务器端来执行Ping操作,然后把结果返回给Blazor前端。服务器不受浏览器的安全限制,可以正常使用Ping类。

比如后端写一个Ping控制器:

[ApiController]
[Route("api/ping")]
public class PingController : ControllerBase
{
    [HttpGet("{ip}")]
    public async Task<IActionResult> CheckPing(string ip)
    {
        try
        {
            using var pingSender = new Ping();
            PingReply reply = await pingSender.SendPingAsync(ip, 120);
            
            return Ok(new 
            { 
                Success = reply.Status == IPStatus.Success,
                Status = reply.Status.ToString()
            });
        }
        catch (Exception ex)
        {
            return BadRequest(new { Error = $"Ping失败:{ex.Message}" });
        }
    }
}

然后修改Blazor前端的代码,调用这个后端API:

@page "/test"
@inject HttpClient Http
@using System.Net.NetworkInformation;
@using System.Text;

<h1>Ping测试</h1>
<p>Ping结果:@resultText</p>
<form>
    <button class="btn btn-primary" @onclick="PingDevice">测试192.168.0.1</button>
</form>

@code {
    private string resultText = "未测试";

    private async Task PingDevice()
    {
        resultText = "正在Ping...";
        try
        {
            var pingResult = await Http.GetFromJsonAsync<PingResult>("api/ping/192.168.0.1");
            
            if (pingResult.Success)
            {
                resultText = "Ping成功!";
            }
            else
            {
                resultText = $"Ping失败:{pingResult.Status}";
            }
        }
        catch (Exception ex)
        {
            resultText = $"请求失败:{ex.Message}";
        }
    }

    private class PingResult
    {
        public bool Success { get; set; }
        public string? Status { get; set; }
        public string? Error { get; set; }
    }
}

2. 前端替代方案(仅用于简单网络检测)

如果你的需求只是检测网络是否连通(而不是必须Ping特定IP),可以用浏览器原生的navigator.onLineAPI,或者尝试请求一个服务器上的小资源(比如空文本文件)来判断:

private async Task CheckNetwork()
{
    if (!navigator.OnLine)
    {
        resultText = "当前无网络";
        return;
    }
    
    try
    {
        // 请求一个服务器上的小资源
        await Http.GetAsync("/favicon.ico");
        resultText = "网络连通正常";
    }
    catch
    {
        resultText = "网络异常";
    }
}

但这个方法无法替代Ping特定设备的功能,只能判断是否能连接到你的服务器。

调试小贴士

你原来的代码里catch (Exception)没有任何处理,这会导致你看不到任何错误信息,非常不利于调试。建议在catch块里添加日志或者页面提示,比如用Console.WriteLine输出异常信息,或者把错误显示到页面上。

内容的提问来源于stack exchange,提问作者JohnyCage1948

火山引擎 最新活动