在本篇文章中,我们将介绍一个使用 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( 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(); } 路由器重启流程 重启路由器的过程分为两个主要步骤:登录路由器和执行重启命令。 
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< 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),然后发送重启请求: 
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 ;     } } 完整代码示例 下面是完整的定时重启路由器程序代码: 
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 ;             }         }     } } 
实现原理详解 HTTP请求模拟 本程序本质上是通过模拟浏览器行为来访问路由器的管理界面。我们使用 HttpClient 类来发送HTTP请求,并使用 CookieContainer 来管理会话状态。这种方式无需使用浏览器自动化工具(如Selenium),效率更高,资源占用更少。 
登录过程分析 登录一个路由器管理界面通常涉及以下几个步骤: 
获取初始Cookie 获取安全令牌 :许多路由器会生成一个随机令牌用于防止CSRF攻击 处理凭据 发送POST请求 验证登录成功 在我们的实现中,通过访问 /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( 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 确保定时器会重复触发,而不是只执行一次。 
适配不同路由器 本程序专为特定型号的路由器编写,如果要适配其他品牌或型号的路由器,需要根据实际情况修改以下几个方面: 
路由器地址和登录凭据 private   static   string  routerAddress =  "http://192.168.18.1" ;  // 路由器IP地址 private   static   string  username =  "user" ;  // 用户名 private   static   string  password =  "yourpassword" ;  // 密码 登录流程 不同路由器有不同的登录API和安全机制。需要分析目标路由器的登录请求,包括: 
安全令牌获取方式 密码编码方式(有些路由器可能使用MD5而非Base64) 登录参数的名称和格式 重启命令路径 路由器重启命令的API端点和参数也各不相同: 
重启页面的URL(如本例中的 /html/ssmp/restore/resetfactory.asp ) 重启API端点(如本例中的 set.cgi?x=… ) 安全令牌的获取和传递方式 总结 定时重启路由器是一个简单但实用的网络维护工具,通过模拟HTTP请求和自动化交互实现了路由器管理界面的操作自动化。本程序提供了一个完整的实现示例,包括登录验证、指令执行和定时触发功能,可以根据具体路由器型号和需求进行调整和扩展。 
阅读原文:原文链接 
 该文章在 2025/5/14 10:04:54 编辑过