LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

C# 实现路由器自动重启服务的实现

admin
2025年5月13日 12:16 本文热度 5

在本篇文章中,我们将介绍一个使用 C# 编写的程序,该程序可以自动登录到路由器并定时重启它。程序利用 HttpClient 和异步编程来执行网络请求,确保高效性。下面将详细分析程序的各个部分及其功能。

其实用telnet来实现更简单,问题是一般的路由器没有提供这个功能。

功能概述

我们将开发一个控制台应用程序,具有以下功能:

  • 自动登录路由器管理界面
  • 定时执行路由器重启命令(默认1小时一次)
  • 程序启动时立即执行一次重启
  • 完整的错误处理和日志记录

技术实现

所需依赖

using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text.RegularExpressions;

基础配置

首先,我们需要设置路由器的基本信息:

private static string routerAddress = "http://192.168.18.1";
private static string username = "user"// 根据路由器设置修改  
private static string password = "yourpassword"// 替换为您的路由器密码  
private static CookieContainer cookieContainer = new CookieContainer();
private static HttpClientHandler handler;
private static HttpClient client;

主程序结构

static async Task Main(string[] args)
{
    Console.WriteLine("路由器定时重启程序已启动");

    // 初始化HTTP客户端
    InitializeHttpClient();

    // 设置定时器 - 24小时执行一次
    SetupTimer();

    // 初次启动也执行一次  
    await RebootRouter();

    Console.WriteLine("按任意键退出...");
    Console.ReadKey();
}

HTTP客户端初始化

private static void InitializeHttpClient()
{
    handler = new HttpClientHandler
    {
        CookieContainer = cookieContainer,
        UseCookies = true
    };

    client = new HttpClient(handler)
    {
        BaseAddress = new Uri(routerAddress),
        Timeout = TimeSpan.FromSeconds(30)
    };

    // 设置默认的User-Agent和其他请求头
    client.DefaultRequestHeaders.Add("User-Agent""Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36");
    client.DefaultRequestHeaders.Add("Accept""text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
    client.DefaultRequestHeaders.Add("Accept-Language""en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7");
}

定时器设置

private static void SetupTimer()
{
    var timer = new System.Timers.Timer(160 * 60 * 1000); // 1小时
    timer.Elapsed += async (sender, e) =>
    {
        try
        {
            await RebootRouter();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"[{DateTime.Now}] 定时重启出错: {ex.Message}");
        }
    };
    timer.AutoReset = true;
    timer.Start();
}

路由器重启流程

重启路由器的过程分为两个主要步骤:登录路由器和执行重启命令。

private static async Task RebootRouter()
{
    try
    {
        Console.WriteLine($"[{DateTime.Now}] 开始重启路由器...");

        // 第1步:登录到路由器  
        bool loginSuccess = await LoginToRouter();

        if (loginSuccess)
        {
            // 第2步:执行重启命令  
            bool rebootSuccess = await ExecuteReboot();

            if (rebootSuccess)
            {
                Console.WriteLine($"[{DateTime.Now}] 路由器重启命令已发送成功!");
            }
            else
            {
                Console.WriteLine($"[{DateTime.Now}] 路由器重启命令发送失败!");
            }
        }
        else
        {
            Console.WriteLine($"[{DateTime.Now}] 登录路由器失败!");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"[{DateTime.Now}] 错误: {ex.Message}");
    }
}

登录路由器

登录过程模拟了浏览器的行为,包括获取随机计数值、设置Cookie、发送登录请求等步骤:

private static async Task<bool> LoginToRouter()
{
    try
    {
        // 首先访问登录页面获取初始Cookie
        var initialResponse = await client.GetAsync("/");

        // 获取随机计数值(用于安全验证)
        var randCountResponse = await client.PostAsync("/asp/GetRandCount.asp", null);
        string randCount = await randCountResponse.Content.ReadAsStringAsync();

        Console.WriteLine($"获取到的随机计数: {randCount}");

        // 设置初始Cookie
        cookieContainer.Add(new Uri(routerAddress), new Cookie("Cookie""body:Language:chinese:id=-1"));
        cookieContainer.Add(new Uri(routerAddress), new Cookie("MenuJumpIndex""0"));

        // 准备登录参数
        var loginParams = new Dictionary<stringstring>
        {
            { "UserName", username },
            { "PassWord", Convert.ToBase64String(Encoding.UTF8.GetBytes(password)) },
            { "Language""chinese" },
            { "x.X_HW_Token", randCount }
        };

        // 创建表单内容
        var loginContent = new FormUrlEncodedContent(loginParams);

        // 添加引用页头
        client.DefaultRequestHeaders.Referrer = new Uri(routerAddress);

        // 发送登录请求
        var loginResponse = await client.PostAsync("/login.cgi", loginContent);

        // 检查登录结果
        if (loginResponse.IsSuccessStatusCode)
        {
            // 获取登录后的页面内容
            string responseContent = await loginResponse.Content.ReadAsStringAsync();

            // 登录后应该被重定向到index.asp
            var indexResponse = await client.GetAsync("/index.asp");

            if (indexResponse.IsSuccessStatusCode)
            {
                Console.WriteLine("登录成功!");
                returntrue;
            }
        }

        returnfalse;
    }
    catch (Exception ex)
    {
        Console.WriteLine($"登录过程中出错: {ex.Message}");
        returnfalse;
    }
}

执行重启命令

执行重启命令需要先获取页面中的安全令牌(onttoken),然后发送重启请求:

private static async Task<bool> ExecuteReboot()
{
    try
    {
        // 重启功能在 resetfactory.asp 页面
        Console.WriteLine("访问重启页面...");
        var resetPageUrl = "/html/ssmp/restore/resetfactory.asp";
        var resetPageResponse = await client.GetAsync(resetPageUrl);

        if (!resetPageResponse.IsSuccessStatusCode)
        {
            Console.WriteLine($"访问重启页面失败,状态码: {resetPageResponse.StatusCode}");
            returnfalse;
        }

        // 获取页面内容以提取 onttoken
        var pageContent = await resetPageResponse.Content.ReadAsStringAsync();

        // 匹配模式 <input type="hidden" name="onttoken" id="hwonttoken" value="...">
        var tokenMatch = Regex.Match(pageContent,
            @"<input\s+type=""hidden""\s+name=""onttoken""\s+id=""hwonttoken""\s+value=""([^""]+)""",
            RegexOptions.IgnoreCase);

        if (!tokenMatch.Success)
        {
            Console.WriteLine("无法找到onttoken值");
            returnfalse;
        }

        string tokenValue = tokenMatch.Groups[1].Value;
        Console.WriteLine($"获取到的onttoken值: {tokenValue}");

        // 设置重启请求的引用页
        client.DefaultRequestHeaders.Referrer = new Uri($"{routerAddress}{resetPageUrl}");

        // 准备重启请求参数
        var rebootParams = new Dictionary<stringstring>
        {
            { "x.X_HW_Token", tokenValue }
        };

        // 创建重启请求内容
        var rebootContent = new FormUrlEncodedContent(rebootParams);

        // 发送重启请求
        var rebootUrl = "set.cgi?x=InternetGatewayDevice.X_HW_DEBUG.SMP.DM.ResetBoard&RequestFile=html/ssmp/restore/resetfactory.asp";
        var rebootResponse = await client.PostAsync(rebootUrl, rebootContent);

        if (rebootResponse.IsSuccessStatusCode)
        {
            Console.WriteLine("重启命令已成功发送");
            returntrue;
        }
        else
        {
            Console.WriteLine($"重启命令发送失败,状态码: {rebootResponse.StatusCode}");
            var responseContent = await rebootResponse.Content.ReadAsStringAsync();
            Console.WriteLine($"响应内容: {responseContent}");
            returnfalse;
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"执行重启时出错: {ex.Message}");
        returnfalse;
    }
}

完整代码示例

下面是完整的定时重启路由器程序代码:

using System;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace AppRebootRouter
{
    class Program
    {

        privatestaticstring routerAddress = "http://192.168.18.1";
        privatestaticstring username = "user"// 根据路由器设置修改  
        privatestaticstring password = "yqv2psyy"// 替换为您的路由器密码  
        privatestatic CookieContainer cookieContainer = new CookieContainer();
        privatestatic HttpClientHandler handler;
        privatestatic HttpClient client;

        static async Task Main(string[] args)
        
{
            Console.WriteLine("路由器定时重启程序已启动");

            // 创建一个HttpClient实例,这个一直会用的
            handler = new HttpClientHandler
            {
                CookieContainer = cookieContainer,
                UseCookies = true
            };

            client = new HttpClient(handler)
            {
                BaseAddress = new Uri(routerAddress),
                Timeout = TimeSpan.FromSeconds(30)
            };

            // 设置默认的User-Agent  
            client.DefaultRequestHeaders.Add("User-Agent""Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36");
            client.DefaultRequestHeaders.Add("Accept""text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7");
            client.DefaultRequestHeaders.Add("Accept-Language""en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7");

            // 设置定时器 - 使用更可靠的方式实现定时功能  
            var timer = new System.Timers.Timer(24 * 60 * 60 * 1000); // 24小时  
            timer.Elapsed += async (sender, e) =>
            {
                try
                {
                    await RebootRouter();
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[{DateTime.Now}] 定时重启出错: {ex.Message}");
                }
            };
            timer.AutoReset = true;
            timer.Start();

            // 初次启动也执行一次  
            await RebootRouter();

            Console.WriteLine("按任意键退出...");
            Console.ReadKey();
        }

        private static async Task RebootRouter()
        
{
            try
            {
                Console.WriteLine($"[{DateTime.Now}] 开始重启路由器...");

                // 第1步:登录到路由器  
                bool loginSuccess = await LoginToRouter();

                if (loginSuccess)
                {
                    // 第2步:执行重启命令  
                    bool rebootSuccess = await ExecuteReboot();

                    if (rebootSuccess)
                    {
                        Console.WriteLine($"[{DateTime.Now}] 路由器重启命令已发送成功!");
                    }
                    else
                    {
                        Console.WriteLine($"[{DateTime.Now}] 路由器重启命令发送失败!");
                    }
                }
                else
                {
                    Console.WriteLine($"[{DateTime.Now}] 登录路由器失败!");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"[{DateTime.Now}] 错误: {ex.Message}");
            }
        }

        privatestatic async Task<bool> LoginToRouter()
        {
            try
            {
                // 首先访问登录页面获取一些初始Cookie  
                var initialResponse = await client.GetAsync("/");

                // 获取随机计数值  
                var randCountResponse = await client.PostAsync("/asp/GetRandCount.asp", null);
                string randCount = await randCountResponse.Content.ReadAsStringAsync();

                Console.WriteLine($"获取到的随机计数: {randCount}");

                // 设置初始Cookie  
                cookieContainer.Add(new Uri(routerAddress), new Cookie("Cookie""body:Language:chinese:id=-1"));
                cookieContainer.Add(new Uri(routerAddress), new Cookie("MenuJumpIndex""0"));

                // 准备登录参数  
                var loginParams = new Dictionary<stringstring>
                {
                    { "UserName", username },
                    { "PassWord", Convert.ToBase64String(Encoding.UTF8.GetBytes(password)) },
                    { "Language""chinese" },
                    { "x.X_HW_Token", randCount }
                };

                // 创建表单内容  
                var loginContent = new FormUrlEncodedContent(loginParams);

                // 添加引用页头  
                client.DefaultRequestHeaders.Referrer = new Uri(routerAddress);

                // 发送登录请求  
                var loginResponse = await client.PostAsync("/login.cgi", loginContent);

                // 检查登录结果  
                if (loginResponse.IsSuccessStatusCode)
                {
                    // 获取登录后的页面内容  
                    string responseContent = await loginResponse.Content.ReadAsStringAsync();

                    // 登录后应该被重定向到index.asp  
                    var indexResponse = await client.GetAsync("/index.asp");

                    if (indexResponse.IsSuccessStatusCode)
                    {
                        Console.WriteLine("登录成功!");
                        returntrue;
                    }
                }

                returnfalse;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"登录过程中出错: {ex.Message}");
                returnfalse;
            }
        }

        privatestatic async Task<bool> ExecuteReboot()
        {
            try
            {
                // 重启功能在 resetfactory.asp 页面  
                Console.WriteLine("访问重启页面...");
                var resetPageUrl = "/html/ssmp/restore/resetfactory.asp";
                var resetPageResponse = await client.GetAsync(resetPageUrl);

                if (!resetPageResponse.IsSuccessStatusCode)
                {
                    Console.WriteLine($"访问重启页面失败,状态码: {resetPageResponse.StatusCode}");
                    returnfalse;
                }

                // 获取页面内容以提取 onttoken  
                var pageContent = await resetPageResponse.Content.ReadAsStringAsync();

                // 匹配模式 <input type="hidden" name="onttoken" id="hwonttoken" value="...">  
                var tokenMatch = Regex.Match(pageContent,
                    @"<input\s+type=""hidden""\s+name=""onttoken""\s+id=""hwonttoken""\s+value=""([^""]+)""",
                    RegexOptions.IgnoreCase);

                if (!tokenMatch.Success)
                {
                    Console.WriteLine("无法找到onttoken值");
                    returnfalse;
                }

                string tokenValue = tokenMatch.Groups[1].Value;
                Console.WriteLine($"获取到的onttoken值: {tokenValue}");

                // 设置重启请求的引用页  
                client.DefaultRequestHeaders.Referrer = new Uri($"{routerAddress}{resetPageUrl}");

                // 准备重启请求参数  
                var rebootParams = new Dictionary<stringstring>
                {
                    { "x.X_HW_Token", tokenValue }
                };

                // 创建重启请求内容  
                var rebootContent = new FormUrlEncodedContent(rebootParams);

                // 发送重启请求  
                var rebootUrl = "set.cgi?x=InternetGatewayDevice.X_HW_DEBUG.SMP.DM.ResetBoard&RequestFile=html/ssmp/restore/resetfactory.asp";
                var rebootResponse = await client.PostAsync(rebootUrl, rebootContent);

                if (rebootResponse.IsSuccessStatusCode)
                {
                    Console.WriteLine("重启命令已成功发送");
                    returntrue;
                }
                else
                {
                    Console.WriteLine($"重启命令发送失败,状态码: {rebootResponse.StatusCode}");
                    var responseContent = await rebootResponse.Content.ReadAsStringAsync();
                    Console.WriteLine($"响应内容: {responseContent}");
                    returnfalse;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"执行重启时出错: {ex.Message}");
                returnfalse;
            }
        }
    }
}

实现原理详解

HTTP请求模拟

本程序本质上是通过模拟浏览器行为来访问路由器的管理界面。我们使用HttpClient类来发送HTTP请求,并使用CookieContainer来管理会话状态。这种方式无需使用浏览器自动化工具(如Selenium),效率更高,资源占用更少。

登录过程分析

登录一个路由器管理界面通常涉及以下几个步骤:

  1. 获取初始Cookie
    :访问首页以获取初始会话Cookie
  2. 获取安全令牌
    :许多路由器会生成一个随机令牌用于防止CSRF攻击
  3. 处理凭据
    :通常密码会进行某种形式的编码(如Base64)
  4. 发送POST请求
    :将用户名、密码和安全令牌作为表单数据提交
  5. 验证登录成功
    :通常通过访问只有登录后才能访问的页面来验证

在我们的实现中,通过访问/asp/GetRandCount.asp获取随机计数值,并使用它作为安全令牌。密码使用Base64编码后发送,这是许多路由器常见的做法。

重启命令执行

执行重启命令同样需要先获取安全令牌,这通常包含在页面的隐藏表单字段中。在这个例子中,我们使用正则表达式从重启页面的HTML内容中提取onttoken值:

var tokenMatch = Regex.Match(pageContent,
    @"<input\s+type=""hidden""\s+name=""onttoken""\s+id=""hwonttoken""\s+value=""([^""]+)""",
    RegexOptions.IgnoreCase);

获取到令牌后,我们将其作为参数发送到路由器的重启API端点:

var rebootUrl = "set.cgi?x=InternetGatewayDevice.X_HW_DEBUG.SMP.DM.ResetBoard&RequestFile=html/ssmp/restore/resetfactory.asp";

定时执行机制

我们使用System.Timers.Timer类来实现定时功能,设置为每1小时执行一次重启操作:

var timer = new System.Timers.Timer(160 * 60 * 1000); // 1小时  
timer.Elapsed += async (sender, e) => {
    try {
        await RebootRouter();
    } catch (Exception ex) {
        Console.WriteLine($"[{DateTime.Now}] 定时重启出错: {ex.Message}");
    }
};
timer.AutoReset = true;
timer.Start();

AutoReset = true确保定时器会重复触发,而不是只执行一次。

适配不同路由器

本程序专为特定型号的路由器编写,如果要适配其他品牌或型号的路由器,需要根据实际情况修改以下几个方面:

路由器地址和登录凭据

private static string routerAddress = "http://192.168.18.1"// 路由器IP地址
private static string username = "user"// 用户名
private static string password = "yourpassword"// 密码

登录流程

不同路由器有不同的登录API和安全机制。需要分析目标路由器的登录请求,包括:

  • 登录API端点(如本例中的/login.cgi
  • 安全令牌获取方式
  • 密码编码方式(有些路由器可能使用MD5而非Base64)
  • 登录参数的名称和格式

重启命令路径

路由器重启命令的API端点和参数也各不相同:

  • 重启页面的URL(如本例中的/html/ssmp/restore/resetfactory.asp
  • 重启API端点(如本例中的set.cgi?x=…
  • 安全令牌的获取和传递方式

总结

定时重启路由器是一个简单但实用的网络维护工具,通过模拟HTTP请求和自动化交互实现了路由器管理界面的操作自动化。本程序提供了一个完整的实现示例,包括登录验证、指令执行和定时触发功能,可以根据具体路由器型号和需求进行调整和扩展。


阅读原文:原文链接


该文章在 2025/5/14 10:04:54 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2025 ClickSun All Rights Reserved