【Java】ChatGPT帮我完成了一个需求,实现了Java和Python自动ping IP的功能

373 阅读4分钟

最近马斯克投资的Openai,推出一个新的模型,据说可以让程序员下岗,怀着好奇的心情,我去试了一下:

首先是一段Springboot ping某个ip并将返回的结果处理后通过io流存在文件中的需求:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;

@Component
public class PingTask {
    @Value("${ip}")
    private String ip;

    @Value("${ping_result.txt}")
    private String logFile;

    @Scheduled(cron = "0/20 * * * * ?")
    public void ping() {
        try (BufferedReader reader = new BufferedReader(new InputStreamReader(
                Runtime.getRuntime().exec("ping " + ip + " -n 1 -w 50").getInputStream(),"GBK"));
             PrintWriter writer = new PrintWriter(new FileWriter(logFile, true))) {
            String line;
            int count = 0;
            int dcount = 0;
            double time = 0.0;
            int ttl = 0;
            while ((line = reader.readLine()) != null) {
                if (line.contains("TTL=")) {
                    String[] parts = line.split(" ");
                    time += Double.parseDouble(parts[parts.length - 2].replace("时间=", "").replace("ms", ""));
                    ttl += Integer.parseInt(parts[parts.length - 1].replace("TTL=", ""));
                    count++;
                }
                if (line.contains("请求超时") ||line.contains("无法访问")) {
                    dcount++;

                }
            }
            if (count > 0) {
                time /= count;
                ttl /= count;
                writer.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
                        + " 平均返回时间:" + time + " 路程:" + ttl);
            }
            if (dcount > 0) {
                writer.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
                        + " 连接断开了");
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

然后是普通java脚本版本的: 原版:

import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class MyTask implements Runnable {
    private String ip;

    public MyTask(String ip) {
        this.ip = ip;
    }

    public void run() {
        String result = ping(ip); // 调用ping方法
        saveResult(result); // 调用saveResult方法保存结果
    }

    private String ping(String ip) {
        // 使用java.lang.Runtime类的exec方法执行ping命令,并获取返回结果
        // 这里省略了实现细节
        // ...
        StringBuilder sb = new StringBuilder(); // 用于存储ping命令的输出结果

        // 使用java.lang.Runtime类的exec方法执行ping命令
        Process process = Runtime.getRuntime().exec("ping " + ip);

        // 读取ping命令的输出结果
        try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream()))) {
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line).append("\n");
            }
        }

        return sb.toString();
        
    }

    private void saveResult(String result) {
        try (BufferedWriter bw = new BufferedWriter(new FileWriter(".\\ping_result.txt", true))) {
            bw.write(result); // 将结果写入文件
            bw.newLine(); // 换行
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[]args){
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
        executor.scheduleAtFixedRate(new MyTask("ip"), 0, 20, TimeUnit.SECONDS);
        // 在0秒后开始执行,然后每隔20秒执行一次
    }
}

此外,它主动还提供了第二种解决方案:

import java.net.InetAddress;

public class Main {
  public static void main(String[] args) throws Exception {
    String ip = "192.168.1.1";
    String result = ping(ip);
    System.out.println(result);
  }

  private static String ping(String ip) throws Exception {
    StringBuilder sb = new StringBuilder(); // 用于存储ping命令的输出结果

    InetAddress address = InetAddress.getByName(ip);
    boolean reachable = address.isReachable(5000); // 指定超时时间为5秒

    sb.append("Address: ").append(ip).append("\n");
    sb.append("Reachable: ").append(reachable);

    return sb.toString();
  }
}

虽然直接运行不了,自己稍微改动后可以运行,代码如下:

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;


public class MyTask implements Runnable {
    public static void main(String[] args) {
        ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
        executor.scheduleAtFixedRate(new MyTask(), 0, 20, TimeUnit.SECONDS);
        // 在0秒后开始执行,然后每隔20秒执行一次
    }

    public void run() {
        try {
            ping();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void ping() throws IOException {
        // 使用java.lang.Runtime类的exec方法执行ping命令,并获取返回结果

        // 使用java.lang.Runtime类的exec方法执行ping命令
        Process process = Runtime.getRuntime().exec("ping ${ip} -n 1 -w 50");

        // 读取ping命令的输出结果
        try (BufferedReader br = new BufferedReader(new InputStreamReader(process.getInputStream(), "GBK"));
             PrintWriter writer = new PrintWriter(new FileWriter("${ping_result.txt}", true))) {
            String line;
            int count = 0;
            int dcount = 0;
            double time = 0.0;
            int ttl = 0;
            while ((line = br.readLine()) != null) {
                if (line.contains("TTL=")) {
                    String[] parts = line.split(" ");
                    time += Double.parseDouble(parts[parts.length - 2].replace("时间=", "").replace("ms", ""));
                    ttl += Integer.parseInt(parts[parts.length - 1].replace("TTL=", ""));
                    count++;
                }
                if (line.contains("请求超时") || line.contains("无法访问")) {
                    dcount++;
                }

            }
            if (count > 0) {
                time /= count;
                ttl /= count;
                writer.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
                        + " 平均返回时间:" + time + " 路程:" + ttl);
            }
            if (dcount > 0) {
                writer.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date())
                        + " 连接断开了");
            }
        }
    }
}

如果不知道在Linux还是Windows上运行,可以将代码改动如下:

import org.junit.Test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;


public class PingDeviceUtils {
    /**
     * @param ipAddress  ip地址
     * @param pingTimes  次数(一次ping,对方返回的ping的结果的次数)
     * @param timeOut    超时时间 单位ms(ping不通,设置的此次ping结束时间)
     * @return
     */
    @Test
    public static Boolean Ping(String ipAddress, int pingTimes, int timeOut){

        BufferedReader in = null;
        String pingCommand = null;
        Runtime r = Runtime.getRuntime();
        String osName = System.getProperty("os.name");
        System.out.println("项目所在系统是:" +osName);
        if(osName.contains("Windows")){
            //将要执行的ping命令,此命令是windows格式的命令
            pingCommand = "ping " + ipAddress + " -n " + pingTimes    + " -w " + timeOut;
        }else{
            //将要执行的ping命令,此命令是Linux格式的命令
            //-c:次数,-w:超时时间(单位/ms)  ping -c 10 -w 0.5 192.168.120.206
            pingCommand = "ping " + " -c " + "4" + " -w " + "2 " + ipAddress;
        }
        try {
            //执行命令并获取输出
            Process p = r.exec(pingCommand);
            if (p == null) {
                return false;
            }
            in = new BufferedReader(new InputStreamReader(p.getInputStream()));
            int connectedCount = 0;
            String line = null;
            while ((line = in.readLine()) != null) {
                connectedCount += getCheckResult(line,osName);
            }
            //如果出现类似=23 ms ttl=64(TTL=64 Windows)这样的字样,出现的次数=测试次数则返回真
            //return connectedCount == pingTimes;
            System.out.println("ping通设备IP的次数为:" +connectedCount);
            return connectedCount >= 2 ? true : false;
        } catch (Exception ex) {
            ex.printStackTrace(); //出现异常则返回假
            return false;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    //若line含有=18 ms ttl=64字样,说明已经ping通,返回1,否則返回0.
    private static int getCheckResult(String line,String osName) {
        if(osName.contains("Windows")){
            if(line.contains("TTL=")){
                return 1;
            }
        }else{
            if(line.contains("ttl=")){
                return 1;
            }
        }
        return 0;
    }
}

最后我让他试着将这段代码用Python写出来:

import re
import subprocess
from datetime import datetime
from threading import Timer


def ping():
    # 使用Python的subprocess模块执行ping命令
    result = subprocess.run(["ping", "${ip}", "-n", "1", "-w", "50"], stdout=subprocess.PIPE)
    output = result.stdout.decode("gbk")

    # 读取ping命令的输出结果
    lines = output.split("\n")
    count = 0
    dcount = 0
    time = 0.0
    ttl = 0
    for line in lines:
        if "TTL=" in line:
            time_match = re.search(r"时间=(\d+\.?\d*)", line)
            if time_match:
                time += float(time_match.group(1))
            ttl_match = re.search(r"TTL=(\d+)", line)
            if ttl_match:
                ttl += int(ttl_match.group(1))
            count += 1
        if "请求超时" in line or "无法访问" in line or "常见故障" in line:
            dcount += 1

    if count > 0:
        time /= count
        ttl /= count
        with open(".\\ping_result.txt", "a") as f:
            f.write(f"{datetime.now():%Y-%m-%d %H:%M:%S} 平均返回时间:{time} 路程:{ttl}\n")
    if dcount > 0:
        with open(".\\ping_result.txt", "a") as f:
            f.write(f"{datetime.now():%Y-%m-%d %H:%M:%S} 连接断开了\n")


def main():
    # 使用Python的Threading模块定时执行任务
    Timer(0, ping, ()).start()
    Timer(20, main, ()).start()


main()

我试了一下运行,除了一些小问题稍微改动一下,整体还是可以满足需求的。