Windows 服务中获取本机的 IP 地址

Windows 服务中获取本机的 IP 地址,核心是通过System.Net.NetworkInformationSystem.Net命名空间下的 API,区分IPv4/IPv6内网 / 公网排除回环地址(127.0.0.1),下面是完整的 IP 获取方法,并集成到之前的服务代码中,确保获取的 IP 地址准确且实用。

一、核心 IP 获取方法

先封装通用的 IP 获取工具类,支持获取所有有效 IPv4 地址、首选 IPv4 地址(常用)、公网 IP(需联网),你可根据需求选择使用

cs 复制代码
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;

/// <summary>
/// IP地址获取工具类
/// </summary>
public static class IpHelper
{
    /// <summary>
    /// 获取本机所有有效IPv4地址(排除回环地址、虚拟网卡)
    /// </summary>
    /// <returns>IPv4地址列表</returns>
    public static List<string> GetAllValidIPv4Addresses()
    {
        var ipList = new List<string>();
        try
        {
            // 获取所有网络接口
            foreach (NetworkInterface ni in NetworkInterface.GetAllNetworkInterfaces())
            {
                // 过滤:仅保留启用的、非回环、非隧道的物理/无线网卡
                if (ni.OperationalStatus != OperationalStatus.Up || 
                    ni.NetworkInterfaceType == NetworkInterfaceType.Loopback ||
                    ni.NetworkInterfaceType == NetworkInterfaceType.Tunnel)
                {
                    continue;
                }

                // 获取该网卡的IP地址信息
                foreach (UnicastIPAddressInformation ipInfo in ni.GetIPProperties().UnicastAddresses)
                {
                    // 仅保留IPv4地址,排除回环地址(127.0.0.1)
                    if (ipInfo.Address.AddressFamily == AddressFamily.InterNetwork &&
                        !IPAddress.IsLoopback(ipInfo.Address))
                    {
                        ipList.Add(ipInfo.Address.ToString());
                    }
                }
            }
        }
        catch (Exception ex)
        {
            throw new Exception("获取IPv4地址失败:" + ex.Message);
        }
        return ipList.Distinct().ToList(); // 去重
    }

    /// <summary>
    /// 获取本机首选IPv4地址(第一个有效IPv4)
    /// </summary>
    /// <returns>首选IPv4地址,无则返回空</returns>
    public static string GetPrimaryIPv4Address()
    {
        var allIps = GetAllValidIPv4Addresses();
        return allIps.Count > 0 ? allIps[0] : string.Empty;
    }

    /// <summary>
    /// 获取公网IP地址(需联网,调用第三方接口)
    /// 注意:服务运行账户需有外网访问权限
    /// </summary>
    /// <returns>公网IP,获取失败则返回空</returns>
    public static string GetPublicIPAddress()
    {
        try
        {
            // 调用免费的公网IP查询接口(备选:https://api.ipify.org、https://icanhazip.com)
            using (var client = new WebClient())
            {
                client.Timeout = 5000; // 设置5秒超时
                string publicIp = client.DownloadString("https://ifconfig.me/ip").Trim();
                // 验证是否为合法IPv4
                if (IPAddress.TryParse(publicIp, out IPAddress ip) && ip.AddressFamily == AddressFamily.InterNetwork)
                {
                    return publicIp;
                }
            }
        }
        catch (Exception)
        {
            // 捕获超时/网络异常,返回空即可
        }
        return string.Empty;
    }
}

二、集成到 Windows 服务中

将 IP 获取逻辑添加到之前的服务代码中,比如在服务启动时记录 IP 地址,或在定时任务中使用 IP 信息

cs 复制代码
using System;
using System.ServiceProcess;
using System.Timers;
using System.Threading.Tasks;
using System.Threading;

namespace MultiTimerMultiTaskService
{
    public partial class MultiTimerMultiTaskService : ServiceBase
    {
        private Timer _timerTask1;
        private Timer _timerTask2;

        public MultiTimerMultiTaskService()
        {
            InitializeComponent();
            InitTimers();
        }

        private void InitTimers()
        {
            // 定时器1:每10秒执行,演示获取IP并记录
            _timerTask1 = new Timer
            {
                Interval = 10 * 1000,
                AutoReset = true,
                Enabled = false
            };
            _timerTask1.Elapsed += TimerTask1_Elapsed;

            _timerTask2 = new Timer
            {
                Interval = 30 * 1000,
                AutoReset = true,
                Enabled = false
            };
            _timerTask2.Elapsed += TimerTask2_Elapsed;
        }

        protected override void OnStart(string[] args)
        {
            try
            {
                WriteLog("多定时器多任务服务开始启动...");

                // 服务启动时获取并记录IP地址
                WriteLog("=== 本机网络信息 ===");
                string primaryIp = IpHelper.GetPrimaryIPv4Address();
                WriteLog($"首选内网IPv4:{ (string.IsNullOrEmpty(primaryIp) ? "未获取到" : primaryIp) }");

                var allIps = IpHelper.GetAllValidIPv4Addresses();
                WriteLog($"所有内网IPv4:{ (allIps.Count > 0 ? string.Join(",", allIps) : "未获取到") }");

                string publicIp = IpHelper.GetPublicIPAddress();
                WriteLog($"公网IPv4:{ (string.IsNullOrEmpty(publicIp) ? "未获取到(请检查网络)" : publicIp) }\n");

                // 立即执行任务
                ExecuteTask1Logic();
                ExecuteTask2Logic();

                // 启动定时器
                _timerTask1.Enabled = true;
                _timerTask2.Enabled = true;

                WriteLog("服务启动完成,定时器已运行");
            }
            catch (Exception ex)
            {
                WriteLog($"服务启动失败:{ex.Message}");
                this.Stop();
            }
        }

        protected override void OnStop()
        {
            // 原有停止逻辑...
            try
            {
                if (_timerTask1 != null)
                {
                    _timerTask1.Enabled = false;
                    _timerTask1.Elapsed -= TimerTask1_Elapsed;
                    _timerTask1.Dispose();
                    _timerTask1 = null;
                }

                if (_timerTask2 != null)
                {
                    _timerTask2.Enabled = false;
                    _timerTask2.Elapsed -= TimerTask2_Elapsed;
                    _timerTask2.Dispose();
                    _timerTask2 = null;
                }

                WriteLog("多定时器多任务服务已停止,所有资源已释放");
            }
            catch (Exception ex)
            {
                WriteLog($"服务停止失败:{ex.Message}");
            }
        }

        // 定时器1任务:演示定时获取IP
        private void TimerTask1_Elapsed(object sender, ElapsedEventArgs e)
        {
            var timer = (Timer)sender;
            timer.Enabled = false;

            try
            {
                ExecuteTask1Logic();
            }
            catch (Exception ex)
            {
                WriteLog($"定时器1执行异常:{ex.Message}");
            }
            finally
            {
                timer.Enabled = true;
            }
        }

        private void ExecuteTask1Logic()
        {
            WriteLog("===== 定时器1任务执行(获取IP) =====");
            // 定时任务中获取IP并使用
            string currentIp = IpHelper.GetPrimaryIPv4Address();
            WriteLog($"当前首选内网IP:{currentIp}");
            // 此处可添加业务逻辑(比如用IP标识服务实例、上报IP等)
            WriteLog("===== 定时器1任务执行完成 =====\n");
        }

        private void TimerTask2_Elapsed(object sender, ElapsedEventArgs e)
        {
            var timer = (Timer)sender;
            timer.Enabled = false;

            try
            {
                ExecuteTask2Logic();
            }
            catch (Exception ex)
            {
                WriteLog($"定时器2执行异常:{ex.Message}");
            }
            finally
            {
                timer.Enabled = true;
            }
        }

        private void ExecuteTask2Logic()
        {
            // 原有定时器2逻辑...
            WriteLog("===== 执行定时器2任务(立即/定时触发) =====");

            var taskList = new[]
            {
                Task.Factory.StartNew(() => ExecuteSubTask("定时器2-子任务1(报表生成)", 3000)),
                Task.Factory.StartNew(() => ExecuteSubTask("定时器2-子任务2(邮件发送)", 2500))
            };

            Task.WaitAll(taskList);
            WriteLog("===== 定时器2任务执行完成 =====\n");
        }

        private void ExecuteSubTask(string taskName, int executeTimeMs)
        {
            try
            {
                WriteLog($"{taskName} 开始执行(线程ID:{Thread.CurrentThread.ManagedThreadId})");
                Thread.Sleep(executeTimeMs);
                WriteLog($"{taskName} 执行完成");
            }
            catch (Exception ex)
            {
                WriteLog($"{taskName} 执行失败:{ex.Message}(线程ID:{Thread.CurrentThread.ManagedThreadId})");
            }
        }

        private void WriteLog(string content)
        {
            string logPath = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Logs");
            if (!System.IO.Directory.Exists(logPath))
            {
                System.IO.Directory.CreateDirectory(logPath);
            }

            string logFile = $"ServiceLog_{DateTime.Now:yyyy-MM-dd}.txt";
            string fullPath = System.IO.Path.Combine(logPath, logFile);

            using (var sw = new System.IO.StreamWriter(fullPath, true, System.Text.Encoding.UTF8))
            {
                sw.WriteLine($"{DateTime.Now:yyyy-MM-dd HH:mm:ss.fff} | {content}");
            }
        }
    }
}
相关推荐
2502_911679142 小时前
行业标杆再进化:罗德施瓦茨ZNB8网络分析仪,如何重新定义射频测试精度?
网络
Selenium-Wang2 小时前
动态HTTP隧道代理IP:从配置到实战的完整指南
网络协议·tcp/ip·http
阿湯哥2 小时前
Reactor响应式编程中Flux和FluxSink
运维·服务器·网络
以太浮标2 小时前
华为eNSP模拟器综合实验之- 通过流策略实现Vlan内二/三层隔离
网络·网络协议·华为
flashier2 小时前
ESP32学习笔记_WiFi(3)——HTTP
网络·笔记·单片机·网络协议·学习·http·esp32
桌面运维家2 小时前
vDisk考场环境网络瓶颈怎么定位?快速排查指南
运维·服务器·网络
谢怜822 小时前
计算机网络第四章网络层
网络·计算机网络
我在人间贩卖青春3 小时前
IP协议及以太网协议
网络·网络协议·tcp/ip
zyxqyy&∞3 小时前
HCIP--BGP--2
网络·华为·hcip