65.9K
CodeProject 正在变化。 阅读更多。
Home

外部 IP Windows 通知服务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.87/5 (16投票s)

2014年11月2日

MIT

4分钟阅读

viewsIcon

22771

downloadIcon

941

一个Windows服务,当外部IP地址更改时发送电子邮件通知。

引言

下载 ExternalIPChecker.zip

下载 ExternalIPChecker-noexe.zip

什么是外部IP地址?
外部IP地址是由您的互联网服务提供商分配给您的地址。IP地址是其他电脑从您的局域网(LAN)外部看到的地址。

它取决于ISP(互联网服务提供商)为您设置静态外部IP,或者在大多数情况下像我一样设置动态IP。
    
为了连接到您网络内部的设备,您需要将所有流量(或只是远程桌面连接或Web服务器的流量 - 您想要的端口)重定向到LAN中设备的IP地址。这通常在ISP路由器中很容易设置。
    
您可以看到我的SKY路由器的设置。这应该很容易配置,并且不是本文的主要内容。

那么,如果外部IP发生了变化会怎样?- 您无法访问您已将流量重定向到的本地电脑或设备,因为您不知道必须使用的外部IP地址。本文通过实现一个Windows通知服务来解决这个问题 - 一个Windows服务,在外部IP地址更改后发送包含新IP地址的电子邮件。

背景

要接收外部IP更改的通知,需要一个始终运行的应用程序,该应用程序会检查外部IP地址,如果发生更改,则发送电子邮件通知。对于基于Windows的PC,最好的技术是Windows服务。它们可以配置为在PC启动时运行,它们在后台运行 - 因此,如果您选择了通过计划任务启动的控制台应用程序作为替代方案,您将不会注意到任何控制台应用程序的启动和停止。

 

使用代码

为了获取外部IP地址,我使用的是一项服务。当您在谷歌搜索“我的IP是多少”时,您会得到很多结果。您可以切换到不同的服务,但我正在使用这个服务。
    
http://checkip.dyndns.org/
    
我使用这段代码:

public static string GetExternalIp()
{
    try
    {
       var externalIP = (new WebClient()).DownloadString("http://checkip.dyndns.org/");
             externalIP = (new Regex(@"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}"))
                                 .Matches(externalIP)[0].ToString();
                    return externalIP;
    }
       catch { return null; }

}
    

它解析服务的响应。
    
我定期调用该服务 - 每30分钟一次。这是一个.config文件中的配置,设置以秒为单位。
    
为了发送电子邮件,我使用我的谷歌帐户登录到他们的SMTP服务器,并启用了SSL功能。一些其他SMTP不支持此功能,因此您可以检查并修改该选项。
这是发送电子邮件的代码

public void SendResetEmail(string ipAddress)
{
   try
    {
           var email = new MailMessage
           {
               From = new MailAddress(ConfigurationManager.AppSettings["EmailAddressFrom"])
           };
    
           email.To.Add(new MailAddress(ConfigurationManager.AppSettings["EmailAddressTo"]));
           email.Subject = "External IP Changed!";
           email.IsBodyHtml = true;
           email.Body = "The IP Address is: " + ipAddress;
           var smtpClient = new SmtpClient
           {
                EnableSsl = true
           };
    
          smtpClient.Send(email);
     }
     catch (Exception ex)
     {
         Program.Logger.Log(ex, LoggerExt.LogExtType.Error);
     }
 }

该服务使用一个计时器,该计时器将在时间间隔内触发一个事件并进行检查。
    

private void OnTimedEvent(object sender, ElapsedEventArgs e)
{
      lock (_locker)
      {
         Program.Logger.Log("Elapsed", LoggerExt.LogExtType.Info);
         var externalIPAddress = IPHelper.GetExternalIp();
         Program.Logger.Log(externalIPAddress, LoggerExt.LogExtType.Debug);
         if (!string.IsNullOrEmpty(externalIPAddress) && externalIPAddress != IPHelper.ReadIPFromFile())
         {
               IPHelper.SaveIPToFile(externalIPAddress);
               SendResetEmail(externalIPAddress);
         }
    
     }
}


正如您在这里看到的,我们有一个临界区 - 每次只有一个用户 - 如果两次检查之间的时间间隔足够长,则不需要。获取外部IP地址后,它会与我们最后存储在文件中的IP地址进行比较。如果IP地址不同 - 则发送通知并保存新的IP地址。
    

关注点

有不同的方法来测试Windows服务。一些建议安装服务以附加到进程并调试它。这当然是一种选择,但不是最好的选择,因为对于每次调试,您都必须重新安装服务。另一种选择是根据特殊输入参数启动一个线程,其中 while (true) Thread.Sleep(1000);

    
示例
 

var hadler = new ExternalIPChecker();
    hadler.CallOnStart();
    
    while (true) Thread.Sleep(1000);//only while debug make the main thread to sleep infinitely

But the best option is to use the Debug directives:

#if DEBUG

                var hadler = new ExternalIPChecker();

                hadler.CallOnStart();

                while (true) Thread.Sleep(1000);//only while debug make the main thread to sleep infinitely

#else

           var servicesToRun = new ExternalIPChecker();

            ServiceBase.Run(servicesToRun);

#endif

 

当您从调试模式切换到发布模式时,代码的不同部分将被执行 - 不需要奇怪的魔术输入参数!

 

如何安装?

在发布模式下构建服务项目。将bin文件夹中的release文件夹复制到一个不会被移动的地方(可以在Program Files中创建一个文件夹)。然后在命令提示符中运行脚本

>sc create "ServiceName" binpath= "服务的绝对路径"

请注意一件非常烦人的事情。binpath= "… 应该与空格数完全一致。如果您决定写成 binpath = "… 将永远无法工作!如果您只是遵循语法而没有注意到这个小细节,这可能会让您花费相当长的时间才能理解。
    
如果您想删除该服务
>sc delete "ServiceName"
    
如果您想进行更新,只需停止服务并复制并覆盖新文件。
    
安装服务时,将其配置更改为自动启动 - 在服务首选项中。
    
    
如果您想通知多个人 - 发送多个电子邮件地址 - 您可以轻松地在配置中使用特殊的分隔符指定所有IP地址,然后将它们解析到数组中,循环遍历它们并将电子邮件发送给所有订阅者 - 所有可以从您的本地PC访问您提供的服务的人。
    
希望这篇文章对您有所帮助且易于理解!

 

 

© . All rights reserved.