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}");
            }
        }
    }
}
相关推荐
chian-ocean1 小时前
深入 CANN:使用 `tbe-op` 构建自定义高性能算子
网络
中议视控1 小时前
可编程网络中央控制系统主机通过红外发射棒控制空调电视等红外设备
网络·物联网·5g
数据安全科普王3 小时前
打破中心枷锁:P2P网络如何用“去中心化”重构互联网通信
网络·去中心化·p2p
爱吃烤鸡翅的酸菜鱼3 小时前
CANN ops-nn激活函数与池化算子深度解析
网络·开源·aigc
saber_andlibert4 小时前
TCMalloc底层实现
java·前端·网络
飞凌嵌入式6 小时前
用「EN 18031认证」通关欧盟,这张 “网络安全护照” 已就位
网络·安全·能源
Trouvaille ~6 小时前
TCP Socket编程实战(三):线程池优化与TCP编程最佳实践
linux·运维·服务器·网络·c++·网络协议·tcp/ip
JoySSLLian7 小时前
手把手教你安装免费SSL证书(附宝塔/Nginx/Apache配置教程)
网络·人工智能·网络协议·tcp/ip·nginx·apache·ssl
Zach_yuan7 小时前
自定义协议:实现网络计算器
linux·服务器·开发语言·网络
猫头虎7 小时前
如何解决 OpenClaw “Pairing required” 报错:两种官方解决方案详解
网络·windows·网络协议·macos·智能路由器·pip·scipy