在本篇文章中,我们将介绍一个使用 C# 编写的程序,该程序可以自动登录到路由器并定时重启它。程序利用 HttpClient
和异步编程来执行网络请求,确保高效性。下面将详细分析程序的各个部分及其功能。
其实用telnet来实现更简单,问题是一般的路由器没有提供这个功能。
我们将开发一个控制台应用程序,具有以下功能:
C#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;
首先,我们需要设置路由器的基本信息:
C#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;
C#static async Task Main(string[] args)
{
Console.WriteLine("路由器定时重启程序已启动");
// 初始化HTTP客户端
InitializeHttpClient();
// 设置定时器 - 24小时执行一次
SetupTimer();
// 初次启动也执行一次
await RebootRouter();
Console.WriteLine("按任意键退出...");
Console.ReadKey();
}
C#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");
}
C#private static void SetupTimer()
{
var timer = new System.Timers.Timer(1* 60 * 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();
}
重启路由器的过程分为两个主要步骤:登录路由器和执行重启命令。
C#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、发送登录请求等步骤:
C#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<string, string>
{
{ "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("登录成功!");
return true;
}
}
return false;
}
catch (Exception ex)
{
Console.WriteLine($"登录过程中出错: {ex.Message}");
return false;
}
}
执行重启命令需要先获取页面中的安全令牌(onttoken),然后发送重启请求:
C#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}");
return false;
}
// 获取页面内容以提取 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值");
return false;
}
string tokenValue = tokenMatch.Groups[1].Value;
Console.WriteLine($"获取到的onttoken值: {tokenValue}");
// 设置重启请求的引用页
client.DefaultRequestHeaders.Referrer = new Uri($"{routerAddress}{resetPageUrl}");
// 准备重启请求参数
var rebootParams = new Dictionary<string, string>
{
{ "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("重启命令已成功发送");
return true;
}
else
{
Console.WriteLine($"重启命令发送失败,状态码: {rebootResponse.StatusCode}");
var responseContent = await rebootResponse.Content.ReadAsStringAsync();
Console.WriteLine($"响应内容: {responseContent}");
return false;
}
}
catch (Exception ex)
{
Console.WriteLine($"执行重启时出错: {ex.Message}");
return false;
}
}
下面是完整的定时重启路由器程序代码:
C#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
{
private static string routerAddress = "http://192.168.18.1";
private static string username = "user"; // 根据路由器设置修改
private static string password = "yqv2psyy"; // 替换为您的路由器密码
private static CookieContainer cookieContainer = new CookieContainer();
private static HttpClientHandler handler;
private static 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}");
}
}
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<string, string>
{
{ "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("登录成功!");
return true;
}
}
return false;
}
catch (Exception ex)
{
Console.WriteLine($"登录过程中出错: {ex.Message}");
return false;
}
}
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}");
return false;
}
// 获取页面内容以提取 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值");
return false;
}
string tokenValue = tokenMatch.Groups[1].Value;
Console.WriteLine($"获取到的onttoken值: {tokenValue}");
// 设置重启请求的引用页
client.DefaultRequestHeaders.Referrer = new Uri($"{routerAddress}{resetPageUrl}");
// 准备重启请求参数
var rebootParams = new Dictionary<string, string>
{
{ "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("重启命令已成功发送");
return true;
}
else
{
Console.WriteLine($"重启命令发送失败,状态码: {rebootResponse.StatusCode}");
var responseContent = await rebootResponse.Content.ReadAsStringAsync();
Console.WriteLine($"响应内容: {responseContent}");
return false;
}
}
catch (Exception ex)
{
Console.WriteLine($"执行重启时出错: {ex.Message}");
return false;
}
}
}
}
本程序本质上是通过模拟浏览器行为来访问路由器的管理界面。我们使用HttpClient
类来发送HTTP请求,并使用CookieContainer
来管理会话状态。这种方式无需使用浏览器自动化工具(如Selenium),效率更高,资源占用更少。
登录一个路由器管理界面通常涉及以下几个步骤:
在我们的实现中,通过访问/asp/GetRandCount.asp
获取随机计数值,并使用它作为安全令牌。密码使用Base64编码后发送,这是许多路由器常见的做法。
执行重启命令同样需要先获取安全令牌,这通常包含在页面的隐藏表单字段中。在这个例子中,我们使用正则表达式从重启页面的HTML内容中提取onttoken
值:
C#var tokenMatch = Regex.Match(pageContent,
@"<input\s+type=""hidden""\s+name=""onttoken""\s+id=""hwonttoken""\s+value=""([^""]+)""",
RegexOptions.IgnoreCase);
获取到令牌后,我们将其作为参数发送到路由器的重启API端点:
C#var rebootUrl = "set.cgi?x=InternetGatewayDevice.X_HW_DEBUG.SMP.DM.ResetBoard&RequestFile=html/ssmp/restore/resetfactory.asp";
我们使用System.Timers.Timer
类来实现定时功能,设置为每1小时执行一次重启操作:
C#var timer = new System.Timers.Timer(1* 60 * 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
确保定时器会重复触发,而不是只执行一次。
本程序专为特定型号的路由器编写,如果要适配其他品牌或型号的路由器,需要根据实际情况修改以下几个方面:
C#private static string routerAddress = "http://192.168.18.1"; // 路由器IP地址
private static string username = "user"; // 用户名
private static string password = "yourpassword"; // 密码
不同路由器有不同的登录API和安全机制。需要分析目标路由器的登录请求,包括:
/login.cgi
)路由器重启命令的API端点和参数也各不相同:
/html/ssmp/restore/resetfactory.asp
)set.cgi?x=...
)定时重启路由器是一个简单但实用的网络维护工具,通过模拟HTTP请求和自动化交互实现了路由器管理界面的操作自动化。本程序提供了一个完整的实现示例,包括登录验证、指令执行和定时触发功能,可以根据具体路由器型号和需求进行调整和扩展。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!