C# 从Lava.Lang.Process使用Xamarin ping IP或主机名

C# 从Lava.Lang.Process使用Xamarin ping IP或主机名,c#,android,visual-studio,mono,xamarin.android,C#,Android,Visual Studio,Mono,Xamarin.android,我正在尝试此代码,它始终返回TTL Expired,即使ip或主机名不可访问,超时或任何其他不同的问题: 使用System.Net.NetworkInformation PingReply Reply = await pingo.SendPingAsync(text_ip.Text, 4000, buffer, options); Toast.MakeText(Activity, Reply.Status.ToString(), ToastLength.Long).Show();

我正在尝试此代码,它始终返回
TTL Expired
,即使ip或主机名不可访问,
超时
或任何其他不同的问题:

使用System.Net.NetworkInformation

PingReply Reply = await pingo.SendPingAsync(text_ip.Text, 4000, buffer, options);
        Toast.MakeText(Activity, Reply.Status.ToString(), ToastLength.Long).Show();
        switch (Reply.Status)
        {
            case IPStatus.Success:

                Toast.MakeText(Activity, Reply.Status.ToString(), ToastLength.Long).Show();
                break;

            case IPStatus.TimedOut:

                Toast.MakeText(Activity, Reply.Status.ToString(), ToastLength.Long).Show();
                break;

            case IPStatus.TimeExceeded:

                Toast.MakeText(Activity, Reply.Status.ToString(), ToastLength.Long).Show();
                break;

            case IPStatus.DestinationHostUnreachable:


               Toast.MakeText(Activity, Reply.Status.ToString(), ToastLength.Long).Show();
                break;

            case IPStatus.DestinationNetworkUnreachable:

                Toast.MakeText(Activity, Reply.Status.ToString(), ToastLength.Long).Show();
                break;

            case IPStatus.DestinationUnreachable:

                Toast.MakeText(Activity, Reply.Status.ToString(), ToastLength.Long).Show();
                break;
        }
我发现了一只虫子 (第339行)

并在以下网址报告:

调用系统ping命令并检查退出代码:

if (!ping.WaitForExit (timeout) || (ping.HasExited && ping.ExitCode == 2))
    status = IPStatus.TimedOut;
else if (ping.ExitCode == 0)
    status = IPStatus.Success;
else if (ping.ExitCode == 1)
    status = IPStatus.TtlExpired;
因此,TTL expired是在没有超时、没有错误或成功(退出代码2或0)且退出代码为1时设置的

如果ping根本没有收到任何回复数据包,它将以
code 1
退出。如果同时指定了数据包计数和截止日期,并且截止日期到达时收到的数据包少于计数,则它也将退出,并显示
code 1
。在其他错误中,它以
代码2
退出。否则它将以
代码0
退出。这使得可以使用退出代码查看主机是否处于活动状态

因此,返回值1表示没有收到响应(由于各种原因),在这种情况下,Mono实现设置
TTL expired
状态。我希望在这种情况下会返回超时状态。但是这里似乎没有触发Mono实现的
timeout
检测(例如,因为ping命令在其自身超时之前退出)

因此,还有其他可能的解决方案:

TTL过期
视为主机不活动(但这将忽略真正的
TTL过期
检测)

不管怎样,有人能展示另一种方法吗?例如:

try 
{
    Process ipProcess = runtime.exec("ping -c 1 8.8.8.8");
    int exitValue = ipProcess.waitFor();
    ipProcess.destroy();

    if(exitValue == 0)
    {
        // Success
    } 
    else 
    { 
        // Failure
    }
} 
catch (IOException | InterruptedException e) 
{
    e.printStackTrace();
}
并且要从该
时间(毫秒)
Ttl值
统计数据
数据包丢失
接收数据包
传输数据包
以及来自进程外壳的每个ping序列的其他信息

更新

如何为此目的实施该计划:

public async void add_data(string adresa)
    {
        await Task.Delay(ping_interval);
        if (sekuenca < sekuenca_db && nderprit == false)
        {
            try
            {
                PingReply Reply = await pingo.SendPingAsync(text_ip.Text, timeout, buffer, options);
                switch (Reply.Status)
                {
                    case IPStatus.Success:

                        string sekuena = sekuenca.ToString();
                        mdata.Add(new data() { titulli = "From : " + Reply.Address.ToString(), sekuenca = "Secuenca : " + sekuena + ",", ttl = "TTL : " + Reply.Options.Ttl.ToString() + ",", madhesia = "Send : " + Reply.Buffer.Length.ToString() + " bytes", koha = "Time : " + Reply.RoundtripTime.ToString() + " ms" });
                        mAdapter.NotifyItemInserted(mdata.Count() - 1);
                        if (ndaluar == false)
                        {
                            mRecyclerView.ScrollToPosition(mdata.Count() - 1);
                        }
                        time = time + Reply.RoundtripTime;
                        koha.Add(Convert.ToInt32(Reply.RoundtripTime));
                        add_data(text_ip.Text);
                        break;
public async void add_数据(字符串adresa)
{
等待任务。延迟(ping_间隔);
if(sekuenca
使用操作系统内置的
ping
命令获取ping时间的方法是启动一个进程,读取其输出并解析该数据

因此,必须采取以下步骤:

  • 创建一个
    System.Diagnostics.Process
  • 正确设置其StartInfo参数
  • 重定向其标准输出
  • 从您可以访问的StreamReader中读取输出到字符串中
  • 解析该字符串。为此,您需要了解结果输出的布局
对于第一部分(直到字符串),您的代码可能如下所示:

processp=新流程();
P.StartInfo.FileName=“ping”;
P.StartInfo.Arguments=“-c3 8.8.8.8”;//从8.8.8.8中抽取3个样本
P.StartInfo.UseShellExecute=false;
P.StartInfo.RedirectStandardOutput=true;
字符串readData=“”;
如果(P.Start())
readData=P.StandardOutput.ReadToEnd();//这还将等待进程至少关闭其标准输出
Console.Write(readData.ToString());//执行此操作,您将看到输出的样子
在此之后,您将在
readData
中获得如下输出:

64 bytes from 8.8.8.8: icmp_req=1 ttl=46 time=13.9 ms
64 bytes from 8.8.8.8: icmp_req=2 ttl=46 time=13.9 ms
64 bytes from 8.8.8.8: icmp_req=3 ttl=46 time=13.9 ms

--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 3016ms
rtt min/avg/max/mdev = 13.910/13.926/13.951/0.010 ms
您现在需要做的就是解析感兴趣的相关部分。我建议使用
System.Text.RegularExpressions.Regex
来实现这一点。我假设您对平均往返时间感兴趣。在这种情况下,您需要执行以下步骤:

  • 忽略所有内容,但不包括包含统计信息的最后一行
  • 提取您感兴趣的值
  • 如果需要的值是
    浮点数
    (或
    双精度
    ),请解析该值

        List<string> Lines = new List<string>(readData.Replace("\r\n", "\n").Split('\n'));
    
        while (Lines.Count > 0 && !Lines[0].StartsWith("---"))
            Lines.RemoveAt(0);
    
        // Here, we either have an empty list or a list starting with the line --- 8.8.8.8 ping statistics ---
        float avgPingTime = 0;
        if (Lines.Count > 2)
        {
            // Our important line is now Lines[2], the one starting with "rtt"
            Match M = Regex.Match(Lines[2], @"^rtt [^0-9]*([\d][^\/]+)\/([^\/]+)\/([^\/]+)\/([^ ]+) ms$");
            if (M != null && M.Success) // A match has indeed been found
            {
                string avgPingString = M.Groups[2].Value;
    
                // Now parse that value
                float.TryParse(avgPingString, System.Globalization.NumberStyles.Float, System.Globalization.NumberFormatInfo.InvariantInfo, out avgPingTime);
            }
        }
    
        if (avgPingTime > 0)
        {
            // We parsed the value correctly here
        }
    

    谢谢,但如何使用regex读取异步中每行的ttl、时间、字节等?你能帮忙吗?我想这可能会帮上忙谢谢你,兄弟,我会尝试在我的应用程序中实现。:)我建议你在文档中发布这一点:我认为这没有意义,因为这不是ping的本意。它是这正是适合您的方式,因为您不想让沙箱开销超过ping时间。
    List<string> Lines = new List<string>(readData.Replace("\r\n", "\n").Split('\n'));
    
    while (Lines.Count > 0 && !Lines[0].StartsWith("---"))    
    {
        Match M = Regex.Match(Lines[0], @"^[\d]+ bytes from ([^:]+): [^ ]+ ttl=([\d]+) time=([^ ]+) ms");
    
        if (M != null && M.Success)
        {
            string IP = M.Groups[1].Value;
            string TTL = M.Groups[2].Value;
            string timeStr = M.Groups[3].Value;
    
            Console.WriteLine(String.Format("Ping to {0} took {2} ms with a ttl of {1}", IP, TTL, timeStr));
            // Parsing the timeStr will work the same way as above
        }
    
        Lines.RemoveAt(0);
    }