首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Lava.Lang.Process中的Xamarin连接IP或主机名

用Lava.Lang.Process中的Xamarin连接IP或主机名
EN

Stack Overflow用户
提问于 2017-03-13 17:39:05
回答 1查看 2.2K关注 0票数 0

我正在尝试这段代码,它总是返回TTL Expired,即使ip或主机名是unreachabletimeout或其他任何不同的问题:

using System.Net.NetworkInformation;

代码语言:javascript
复制
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;
        }

我在https://github.com/mono/mono/blob/master/mcs/class/System/System.Net.NetworkInformation/Ping.cs发现了一个bug (第339行)

并在以下网站报道:bug.cgi?id=53284

它调用system命令并检查退出代码:

代码语言:javascript
复制
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过期是在没有超时、没有错误或成功(退出代码2或0)且退出代码为1时设置的。 如果ping完全没有收到任何回复数据包,它将退出code 1。如果指定了数据包计数和截止日期,并且在截止日期到达时收到的数据包少于计数,则它也将使用code 1退出。在其他错误上,它与code 2一起退出。否则,它将与code 0一起退出。这样就可以使用退出代码来查看主机是否还活着。 因此,返回值1表示没有收到响应(出于各种原因),在这种情况下,Mono实现设置了TTL expired状态。我希望在这种情况下会返回超时状态。但是这里似乎没有触发Mono实现的timeout检测(例如,因为ping命令在它自己的超时之前就退出了)。 因此,还有其他可能的解决办法: 将一个TTL expired TTL expired 视为主机而不是活着(但这将忽略真正的检测)

无论如何,能不能有人展示另一种方法来做到这一点,例如:

代码语言:javascript
复制
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();
}

从这个Time in msTtl valueStatisticsPacket LossReceived PacketsTransmited Packets和其他信息中获取每个ping安全的进程外壳?

更新

如何为此目的实施:

代码语言:javascript
复制
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;
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-03-19 15:23:08

使用OS‘buit-in ping命令获取ping时间的方法是启动一个进程,读取其输出并解析该数据。

因此,所需采取的步骤:

  • 创建一个System.Diagnostics.Process
  • 正确设置其StartInfo参数
  • 重定向其StandardOutput
  • 将可以访问的StreamReader输出读入字符串
  • 解析那个字符串。为此,您需要了解结果输出的布局方式。

对于第一部分(直到字符串),您的代码可以如下所示:

代码语言:javascript
复制
Process P = new Process();
P.StartInfo.FileName = "ping";
P.StartInfo.Arguments = "-c 3 8.8.8.8"; // Take 3 samples to 8.8.8.8
P.StartInfo.UseShellExecute = false;
P.StartInfo.RedirectStandardOutput = true;

string readData = "";
if (P.Start())
    readData = P.StandardOutput.ReadToEnd(); // This will also wait for the process to at least close its stdout
Console.Write(readData.ToString()); // Doing this, you will see how the output looks like

在此之后,您将在readData中获得类似这样的输出

代码语言:javascript
复制
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来实现这一点。我想你对平均往返时间感兴趣。在这种情况下,您需要执行以下步骤:

  • 忽略除了包含统计信息的最后一行之外的所有内容。
  • 提取您感兴趣的值。
  • 如果您需要的值是float (或double),请解析该值 列表行=新列表(readData.Replace(“\r\n”,“\n”).Split(‘\n’);Lines.Count>0&!Lines.StartsWith(“-”) Lines.RemoveAt(0);//在这里,我们要么有一个空列表,要么有一个以行开头的列表- 8.8.8.8 ping统计信息-浮动avgPingTime = 0;如果(Lines.Count > 2) { //我们的重要行现在是Lines2,则以"rtt“开头的一行匹配M= Regex.Match(Lines2,@"^rtt ^0-9*(\d+)\/(^\ +) \/(^\+)/(^+) ms$");如果(M != null && M.Success) // A匹配确实找到了{ string avgPingString = M.Groups2.Value;//现在解析该值float.TryParse(avgPingString,System.Globalization.NumberStyles.Float,avgPingString out avgPingTime);} if (avgPingTime > 0) { //我们在这里正确地解析了该值}

但是,如果您对统计数据之前的每一行的统计数据感兴趣,则需要一种不同的方法:

来自8.8.8.8: icmp_req=2 ttl=46 time=13.9 ms的64个字节

有这些行的n,它们都在以---开头的行之前。

代码语言:javascript
复制
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);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/42769997

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档