日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網為廣大站長提供免費收錄網站服務,提交前請做好本站友鏈:【 網站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(50元/站),

點擊這里在線咨詢客服
新站提交
  • 網站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會員:747

1. 概述

  • 本文介紹了一個簡單的嵌入式項目的的開發過程;
  • 從需求到實踐,本文對整個過程做了全面的介紹,本文所介紹的設備容易獲得且價格低廉;
  • 本文涉及了 *linux* 下 C 語言下的網絡編程、網絡廣播、*Magic Packet*、內網穿透、反向代理等概念;
  • 本文所涉及的一些技術概念讀者可以自行參考其它的文章;
  • 本文可能并不適合初學者

2. 需求

  • 家里放了一臺服務器,差不多我所有的東西都在服務器上,不管在家里還是其它地方,都需要連接這臺服務器才能做事情;
  • 這臺服務器白天開著,晚上就關了(省點電:));每天起床以后要想著按一下服務器的電源開關,每天睡覺前要記得把服務器關了;
  • 晚上忘記關服務器,通常不會有什么問題;但有時早上沒有打開服務器,可能就要有麻煩了;
  • 尷尬的時候就是早上沒有打開服務器,然后外出,然后剛好需要登錄服務器,這才想起來服務器沒開;
  • 所以吶,我需要有個機制,可以 **遠程打開我的服務器**,這樣我就不會再出現尷尬了;

3. 簡要解決方案

  • 我們把要完成的這個需求當作一個項目來做,可以把這個項目叫做服務器遠程開機
  • 首先要確保服務器的主板支持網絡喚醒,否則不太好辦,不過現在的絕大多數主板都是支持的(PCI 2.2 以后的主板一般都支持,而 PCI 2.2 的標準是1998年提出的),有些主板可能需要 BIOS 設置,請自行搜索解決方案;
  • 第二是在家里的局域網上要有一個小設備是 24 小時運行的,通過這臺設備在局域網上廣播 Magic Packet 來喚醒服務器,這臺設備應該是一臺低功耗設備,越小越簡單越好;我們姑且把這個設備叫做 wakener
  • 第三是要在這個 wakener 上編寫一個簡單的程序,這個程序可以在局域網上廣播 Magic Packet,以喚醒服務器,這個程序我們稱為 wakeOnLan
  • 第四是要有一個機制可以從互聯網上訪問到這臺 wakener,只有這樣才能從互聯網上操控 wakener 上的軟件,其實這是一個內網穿透的問題,要做到這一點或許需要一臺連接到互聯網上的輕量級服務器(VPS就可以);
  • 這樣我不管在哪里,通過終端(筆記本、臺式機、手機、平板等)登錄家里24小時開機的 wakener,運行 wakeOnLan,就可以打開我的服務器;
  • 這臺24小時運行的設備(wakener)有可能為你完成更多的事情,比如 NAS、遠程開空調等等,但是重要的是完成眼前這個第一步。

4. 技術要點

上面的解決方案顯然非常粗糙,但是這個項目本身確實也比較簡單,沒有必要做非常詳盡的設計方案,所以我們下面僅列出一些可能的要點及解決方法

本項目的基本網絡架構

下面是一個簡單的示意圖,表達了這個項目中各個設備是如何連接和互相影響的,其中 Local Server 是我們要遠程開機的服務器,Server 是一臺連接在互聯網上的 VPS,用于內網穿透

圖1:wake on lan架構圖

Magic Packet

遠程喚醒其實是網卡的一個功能,在 PCI 2.2 之后,信號線上多了一個 PME 信號,主機關閉電源后進入休眠狀態,可以繼續為網卡供電,網卡在收到一個叫做 Magic Packet 的數據包后,檢測出該數據包是發給自己的,則會在 PCI 上發出 PME 信號,從而控制電腦啟動,這個功能被稱為 網絡喚醒

網絡喚醒其實并不復雜,在局域網中,從一臺電腦以廣播的形式發送 Magic Packet,那么在 Magic Packet 中指定的 mac 地址對應的電腦就會被喚醒;

Magic Packet 就是一個指定格式的數據包,其格式為:6 個 0xff,然后 16 組需要被網絡喚醒的電腦的 MAC 地址,比如需要被喚醒的電腦的 MAC 為:00:e0:2b:69:00:03,則 Magic Packet 為(16進制表述):

ff ff ff ff ff ff 
00 e0 2b 69 00 03 00 e0 2b 69 00 03 
00 e0 2b 69 00 03 00 e0 2b 69 00 03 
00 e0 2b 69 00 03 00 e0 2b 69 00 03 
00 e0 2b 69 00 03 00 e0 2b 69 00 03 
00 e0 2b 69 00 03 00 e0 2b 69 00 03 
00 e0 2b 69 00 03 00 e0 2b 69 00 03 
00 e0 2b 69 00 03 00 e0 2b 69 00 03 
00 e0 2b 69 00 03 00 e0 2b 69 00 03

通常 Magic Packet 的廣播使用 UDP 發送,端口號可以任意,通常使用 7 或者 9

關于 Magic Packet 的更多的信息請參考

  • [wikipidia-網絡喚醒](https://zh.wikipedia.org/zh-cn/%E7%B6%B2%E8%B7%AF%E5%96%9A%E9%86%92)
  • [wikipedia-Wake-On-Lan](https://en.wikipedia.org/wiki/Wake-on-LAN)

從圖1中可以看出,Wakener 通過路由器向局域網內廣播 Magic Packet,從而喚醒 Local Server

要注意的是,Magic Packet 只對有線網卡有效,所以,服務器要使用網線連接到路由器上;


內網穿透

在這個項目里,內網穿透指的是:使用一定的技術手段讓我們可以從互聯網上直接訪問到家里的一臺設備上,這臺設備通過普通家用寬帶連接互聯網,家用寬帶可能沒有公網 IP;

如果家里的寬帶有公網 IP,穿透內網并不是一個很困難的事,大致需要三個步驟:

  1. 在家里路由器上設置一個 NAT 讓外網的訪問直接轉發到局域網內某個指定設備的指定端口上;
  2. 局域網中的一個設備(或者路由器本身)向某個有權限的公網服務器發送心跳包,使這個服務器可以知道家里寬帶的公網 IP;
  3. 互聯網上的終端設備通過服務器獲知家里寬帶的公網 IP,直接訪問即可;

如果家里的寬帶沒有公網 IP(大多數寬帶應該是這樣的),穿透內網就要麻煩一些,通常需要使用反向代理來實現,這需要一個公網服務器;

  • 公網服務器上安裝有支持反向代理的服務器端軟件,比如 *sshd*;
  • 局域網的設備上裝有反向代理的客戶端軟件,比如 *ssh*,通過向公網服務器發送反向代理的指令可以建立一個反向代理隧道(*tunnel*),*tunnel* 建立起來以后,訪問公網服務器的某個指定端口將被映射到訪問局域網中某個 IP 地址下的某個端口,從而實現內網穿透;

目前有很多的內網穿透的工具,其原理其實都是反向代理,但通常比直接用 ssh 要好用得多,至少 ssh 在意外斷開后不會自動重連,這些工具都會解決這些問題;

本文所使用的嵌入式 Linux 系統將是 openwrt,理論上可以使用向日葵的內網穿透插件,愿意折騰的讀者可以嘗試折騰一下向日葵插件;

本文在內網穿透上將使用一個叫 frp 的開源項目,后面會給出這個項目的具體網址


其它要面對的麻煩

為硬件燒錄或編譯一個定制的 *Linux* 操作系統,還好本文的例子并不需要自己編譯一個 *Linux*,燒錄就好了;

交叉編譯環境,這個是做嵌入式開發必須面對的,無法回避。


5. 簡單的嵌入式開發步驟

  1. 需求分析
  2. 概要設計和詳細設計
  3. 硬件開發及驗證
  4. 編譯與硬件相適應的操作系統及所需工具
  5. 建立在相應硬件上進行軟件開發的交叉編譯環境;
  6. 嵌入式軟件開發;
  7. 調試

下面我們會依照這個開發步驟去實現我們的方案


6. 具體實踐

需求分析和設計

本項目的開發的需求分析和設計已經在前面完成,鑒于該項目比較簡單,就不做更詳細設計了

硬件開發和驗證

  • 要找一個24小時運行的設備

我有一個早就不用的 迅雷一代賺錢寶(以下簡稱賺錢寶),不知道為何物的自己去百度一下

賺錢寶這個玩意 CPU 用的是 Amlogic S805ARM Cortex-A5 架構,4核1.5GHz,功耗非常低,記住這個 CPU 的型號,記住這個 CPU 是32位的;

圖2:賺錢寶外觀


圖3:賺錢寶主板

這個玩意有 *256M* 內存,1G 的 *Flash*,*100M* 網口和一個 *USB* 口,足夠用了;

以前有一些廠家用這個 *CPU* 做網絡機頂盒,現在應該沒人用了;

淘寶上查了一下,賺錢寶一代是買不到了,但三代(玩客云)還有二手賣,大概在45 - 55元,用的CPU和一代一樣,只是內存大了,如果你想折騰,也可以買一個來玩;

  • 硬件驗證

這個設備的硬件顯然不需要驗證,迅雷已經幫我們驗證了;

實際上,這個設備可以有多種選擇,如果你的路由器是 OEM 的,上面通常運行的都是 openwrt,那么你可以直接使用它;

或者你手頭有閑置的機頂盒等,都有可能用得上;但是通常不建議使用平板,一是太耗電,二是把Android/ target=_blank class=infotextkey>安卓刷成 *Linux* 有難度。

操作系統

賺錢寶上原有的 Linux 應該是迅雷自己編譯的,很難知道迅雷在這個系統上做了什么,所以還是不用為好,需要刷個新的系統,CPU 為 S805 的設備通常都是支持 USB 刷機的,所以其實根本不用把它拆開,直接一條 USB 線就可以刷新系統了;

刷個 openwrt 是比較現實的,有現成的教程,而且 openwrt 資料豐富,便于今后折騰;

刷機教程:[廢物利用之閑置礦渣迅雷賺錢寶一代刷OpenWrt固件發揮余熱_智能設備_什么值得買];

刷機包及相應軟件:(
https://pan.baidu.com/s/1E4Ls05lPHHHhv0Ou8fb7GA);提取碼:ow2l

刷機包提供了 openwrt 18 和 19 兩個,建議刷 openwrt 19(因為我刷的是 openwrt 19)

具體刷機過程自己去享受吧;

刷好的機器應該是可以使用 ssh 登錄的

  • 首先要從你的路由器上找到這臺 openwrt 的 IP 地址,比如為:192.168.2.100,然后用 ssh 登錄,新刷的 openwrt 沒有密碼
ssh [email protected]
  • 我這里登錄以后的樣子,登錄以后一定要改一下 root 的密碼

圖4:ssh登錄openwrt

  • openwrt 還會有一個 web 界面,直接在瀏覽器上輸入 IP 即可進入

圖5:登錄openwrt的web界面


圖6:openwrt的web界面

  • 這臺設備最好不要使用 DHCP,而是使用固定 IP,這樣便于以后遠程登錄,有三種方法設置固定 IP

1. 直接修改配置文件

openwrt 的網絡配置文件放在 /etc/config.NETwork 文件中,可以直接修改這個文件,改成下面這個樣子:

圖7:openwrt 改成固定 IP

2. 使用 openwrt 的 web 界面修改

從瀏覽器登錄 openwrt 的 web 頁面,其密碼與 ssh 的密碼一致,選擇:Network --> Interfaces --> Edit

圖8:通過openwrt的web界面修改固定IP


圖9:通過openwrt的web界面修改固定IP


圖10:通過openwrt的web界面修改固定IP

3. 在路由器上用 *MAC* 地址綁定 IP

實際上就是在路由器上設置 DHCP 每次分配 IP 時,給指定 MAC 地址的設備分配一個固定的 IP,這樣,你的 openwrt 設備就不必設置固定 IP了,每種路由器的設置方法不一樣,我的路由器的界面像這個樣子

圖11:通過路由器設定openwrt的固定IP

 

建立交叉編譯環境

要在賺錢寶上寫程序,需要我們在本地電腦完成編程,然后用交叉編譯的工具編譯成在賺錢寶上可以運行的程序,傳到賺錢寶上才可以在賺錢寶上運行;

所以我們需要有一個工具鏈,對我們編寫的程序進行交叉編譯;

這個工具鏈不是放在 wakener 上的,因為 wakener 通常性能比較差,而且為了節省存儲空間,上面通常只放一些運行時(runtime)庫,不具備開發的能力;所以這個工具鏈要放在另外一臺運行著 Linux 的機器上,也可以運行在虛擬機上,我們把這臺電腦叫做 開發機,建議在開發機上運行 ubuntu

下面是建立這個編譯環境的過程

  • 首先 *ssh* 登錄你剛刷的 *openwrt*,查看你刷的 *openwrt* 的版本號:

 

圖12:查看openwrt的版本號

  • 下載適當的 sdk

去 [openwrt官網](
https://downloads.openwrt.org) 找到你所需要的版本號下的 sdk,要選擇 at91/sama5 目錄下的,這個是 cortex-A5 架構(CPU S805 的架構)的工具鏈

[我的工具鏈的下載地址](
https://downloads.openwrt.org/releases/19.07.7/targets/at91/sama5/openwrt-sdk-19.07.7-at91-sama5_gcc-7.5.0_musl_eabi.Linux-x86_64.tar.xz)

注意這個工具鏈只能運行在 Linux 下,我是運行在 Ubuntu 下,而且 openwrt-19.07.7 的 SDK 只有 64 位 X86 版本;

先將這個工具鏈下載到 ~/Downloads/ 目錄下

wget https://downloads.openwrt.org/releases/19.07.7/targets/at91/sama5/openwrt-sdk-19.07.7-at91-sama5_gcc-7.5.0_musl_eabi.Linux-x86_64.tar.xz -C ~/Downloads/

 

再將其解壓出來

cd ~/Downloads
tar -xvf openwrt-sdk-19.07.7-at91-sama5_gcc-7.5.0_musl_eabi.Linux-x86_64.tar.xz

 

在 ~/Downloads/ 目錄下會建立一個新目錄
openwrt-sdk-19.07.7-at91-sama5_gcc-7.5.0_musl_eabi.Linux-x86_64,進入到這個目錄,可以看到一個 staging_dir 目錄

 

cd openwrt-sdk-19.07.7-at91-sama5_gcc-7.5.0_musl_eabi.Linux-x86_64/ 
ls

這個 staging_dir 目錄下的所有內容就是一個完整的工具鏈,我們可以把這個工具鏈單獨拿出來使用;

我把這個目錄拷貝到了 ~/tooschain/openwrt-a5/ 下,我們之所以放到 ~/toolschain/ 下,是因為我們還可能有別的設備的工具鏈,都放到這個目錄下便于管理

mkdir -p ~/toolschain/openwrt-a5/
cp -fr ~/Downloads/openwrt-sdk-19.07.7-at91-sama5_gcc-7.5.0_musl_eabi.Linux-x86_64/staging_dir/* ~/toolschain/openwrt-a5/

現在我們已經有了一個完整的工具鏈,但這個工具鏈基本上是沒辦法用的,我們需要簡單的配置一下,其實就是設置一些環境變量;

在 HOME 目錄下編輯一個文件 a5.sh,內容如下:

#!/bin/bash
#A5 arm-linux-musl-eabi工具鏈,用于一代賺錢寶openwrt 
export PATH=/home/whowin/toolschain/openwrt-a5/toolchain-arm_cortex-a5+vfpv4_gcc-7.5.0_musl_eabi/bin:$PATH
export STAGING_DIR=/home/whowin/toolschain/openwrt-a5

其中 /home/whowin 為我的 HOME 目錄,你要更改為你的 HOME 目錄;

其實這個文件就是修改了環境變量 PATH,然后增加了一個環境變量 STAGING_DIR,這些設置都是為了能夠正常使用這個工具鏈;

將這個文件設置為可執行,然后把這個文件拷貝到 /bin/ 下:

cd ~
vi a5.sh
(編輯內容并存盤)
chmod 755 a5.sh
sudo cp a5.sh /bin/

放到 /bin/ 目錄下只是為了用起來方便,并沒有特別的含義;

下面我們可以試一下這個工具鏈

source /bin/a5.sh
arm-openwrt-linux-gcc -v

下面是在我的機器上的輸出:

圖13:測試工具鏈

源程序

有了工具鏈就可以編程了,編程的過程要在開發機上完成,不是在 openwrt 下,但是用這個源程序編譯出來的可執行文件是要在 openwrt 下運行的;

下面是這個項目中需要在 openwrt 下運行的程序 wakeOnLan 的源程序

/******************************************************************************
      File Name: wakeOnLan.c
      Description:  向局域網中的計算機發出遠程喚醒的指令
                    該程序將運行在迅雷一代賺錢寶上(已刷openwrt),用于喚醒主機

      Compile:  source /bin/a5.sh
                arm-openwrt-linux-gcc -Wall wakeOnLan.c -o wakeOnLan

      Usage: wakeOnLan [boradcast IP] [MAC]
      Example: sudo ./wakeOnLan 192.168.2.255 00:e0:2b:68:00:03

      Date: 2022-07-26
 *******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <signal.h>
#include <unistd.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>

#define  BIND_PORT         7                   // 端口號
#define  MSG_LEN           102                 // magic packet的長度
#define  USAGE             "wakeOnLan [broadcast IP] [MAC]n" 
"Example: sudo ./wakeOnLan 192.168.1.255 00:e0:2b:69:00:03n"

/*****************************************************
 * Function: int is_IP(char *IP)
 * Description: 檢查IP是否為一個合法的IPv4
 * Return: 1    合法的IPv4
 *         0    非法的IPv4
 *****************************************************/
int is_IP(char *IP) {
  int a, b, c, d;
  char e;

  if (4 == sscanf(IP, "%d.%d.%d.%d%c", &a, &b, &c, &d, &e)) {
    if (a >= 0 && a < 256 &&
        b >= 0 && b < 256 &&
        c >= 0 && c < 256 &&
        d >= 0 && d < 256) {
      return 1;
    }
  }
  return 0;
}

/*************************************************************************
 * Function: int is_MAC(char *mac_str, char *mac)
 * Description: 檢查MAC是否為合法的MAC格式,如果合法,將其轉換成6組數字放到mac中
 * 
 * Return: 1    合法的MAC,char *mac中為轉換后的mac地址
 *         0    非法的MAC
 *************************************************************************/
int is_MAC(char *mac_str, char *mac) {
  int temp[6];
  char e;
  int i;

  if (6 == sscanf(mac_str, "%x:%x:%x:%x:%x:%x%c", &temp[0], &temp[1], &temp[2], &temp[3], &temp[4], &temp[5], &e)) {
    for (i = 0; i < 6; ++i) {
      if (temp[i] < 0 || temp[i] > 255) break;
    }
    if (i == 6) {
      for (i = 0; i < 6; ++i) {
        mac[i] = temp[i];
      }
      return 1;
    }
  }
  return 0;
}

// ===================主程序================================================
int main(int argc, char *argv[]) {
  struct sockaddr_in sin;
  char *broadcast_ip;
  char wol_msg[MSG_LEN + 2];                           // magic packet
  char mac[6];
  int socket_fd;
  int i, j;
  int on = 1;

  // 檢查參數數量
  if (argc < 3) {
    // 參數數量不對
    printf("Incorrect input parameters.n");
    printf(USAGE);
    return -1;
  }

  // 檢查第一個參數是否為一個IP地址
  if (! is_IP(argv[1])) {
    printf("%s is an invalid IPv4.n", argv[1]);
    printf(USAGE);
    return -1;
  }

  // 檢查第二個參數是否為一個MAC地址
  if (! is_MAC(argv[2], mac)) {
    printf("%s is an invalid MAC address.n", argv[2]);
    printf(USAGE);
    return -1;
  }
  printf("MAC is %02x:%02x:%02x:%02x:%02x:%02xn", mac[0], mac[1],mac[2],mac[3],mac[4],mac[5]);

  // 建立socket
  socket_fd = socket(AF_INET, SOCK_DGRAM, 0);
  if (socket_fd < 0) {
    printf("Can not set up socket. Program exits(%d).n", socket_fd);
    return -1;
  }

  // 為IP地址分配內存
  broadcast_ip = calloc(strlen(argv[1]) + 1, sizeof(char));
  if (! broadcast_ip) {
    printf("Can not allocate memory. Program exitsn");
    return -1;
  }
  // 允許在 socket_fd 上發送廣播消息
  setsockopt(socket_fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));

  memset((void *)&sin, 0, sizeof(sin));
  sin.sin_family = AF_INET;
  sin.sin_addr.s_addr = inet_addr(broadcast_ip);       // 廣播IP
  sin.sin_port = htons(BIND_PORT);                     // 端口號

  // 6個 ff
  for (i = 0; i < 6; i++) {
    wol_msg[i] = 0xFF;
  }
  // 16遍 mac 地址
  for (j = 0; j < 16; j++) {
    for (i = 0; i < 6; i++) {
      wol_msg[6 + j * 6 + i] = mac[i];
    }
  }
  // 發送 magic packet
  sendto(socket_fd, &wol_msg, MSG_LEN, 0, (struct sockaddr *)&sin, sizeof(sin));
  close(socket_fd);
  // 釋放前面分配的內存空間
  free(broadcast_ip);

  printf("Magic Packet has been sended.n");

  return 0;
}

這個程序本身比較簡單,注釋比較完整,也沒什么好說明的。

交叉編譯

交叉編譯當然也是在開發機上完成;

假定我們把上面這個源程序放在 ~/wake_on_lan/ 目錄下,下面是交叉編譯的過程:

cd ~/wake_on_lan 
source /bin/a5.sh 
arm-openwrt-linux-gcc -Wall wakeOnLan.c -o wakeOnLan

交叉編譯的過程難免出錯,請自行排錯;

交叉編譯完成的程序是不能在開發機上運行的,需要拷貝到 openwrt 上才能運行,仍然假定 openwrt 的 IP 地址為:192.168.2.100,則可以這樣將已經編譯好的程序拷貝到 openwrt 上,操作在開發機上完成

cd ~/wake_on_lan 
scp wakeOnLan [email protected]:/root/

 

在 openwrt 上運行程序

用 ssh 登錄到 openwrt,登錄后應該就在 /root/ 目錄下,因為 /root/ 是 root 用戶的 HOME 目錄,然后運行程序

ssh [email protected]
./wakeOnLan 192.168.2.255 00:e0:2b:69:00:03

 

第一個參數是局域網上的廣播 IP,第二個參數是要被遠程喚醒的機器的 MAC 地址,請根據你的具體情況進行修改

在我的機器上運行效果是這樣的

圖14:在openwrt上運行wakeOnLan

 

軟件調試

- 這個程序的調試主要是確保程序能夠正確地發出 magic packet,需要在局域網上找另一臺機器進行數據包的監聽,這臺監聽的機器既可以運行 windows 也可以運行 Linux,最好是使用準備遠程喚醒機器作為監聽的機器,我們以一臺運行 ubuntu 的機器為例來完成調試

使用 ubuntu 下的工具 tcpdump 來進行數據包的監聽,tcpdump 必須在 root 權限下運行;

首先在監聽機器上運行 tcpdump

sudo tcpdump -vv -x udp port 7

這行命令的意思就是監聽 udp 端口 7 的數據包,-vv 的意思是顯示詳細的信息,-x 的意思是按照 16 進制顯示,這兩個參數也可以寫成 -vvx

在 openwrt 上運行 wakeOnLan

./wakeOnLan 192.168.2.255 00:e0:2b:69:00:03

 

其中的廣播 IP 和 MAC 地址請按照實際情況填寫

正常情況下,在監聽機器上可以看到程序發出的 Magic Packet,仔細看一下這個數據包的格式是否正確

在我的環境下,看到的輸出如下:

圖15:偵聽Magic Packet

其中黃線標識的部分是 IP 頭,占 20 個字節;綠線標識的部分是 UDP 頭,占 8 個字節,剩下的就是 Magic Packet

如果你正常地偵聽到了一個完整且正確的 Magic Packet,那么恭喜你,就快要成功了;

如果你使用 windows 偵聽 Magic Packet 數據包,通常使用著名的 Wireshark。

局域網內的網絡喚醒測試

- 把需要網絡喚醒的機器關機,如果需要設置 BIOS,要先設置好 BIOS 再關機;

- 使用局域網內的另一臺電腦 ssh 登錄 openwrt,或者使用手機登錄 openwrt,如果使用手機登錄,需要在手機上安裝一個終端 App,我使用安卓手機,安裝的 app 叫 ConnetcBot,推薦大家試一下;

在 openwrt 運行你編寫的程序 wakeOnLan,如果你運氣好,你那臺剛剛關機的電腦應該被默默的打開了電源

但是,通常都沒有那么好的運氣,那么可能的問題如下:
1. 程序里的廣播 IP 是不是正確?
2. Magic Packet 中的 MAC 地址是否正確?
3. Magic Packet 的格式是否正確?
4. 被喚醒的機器是否與 openwrt 在同一個網段?
5. 路由器是否限制了 UDP 的端口 7?
6. 如果以上都沒有問題,恐怕只能懷疑你那臺要被喚醒的機器不支持網絡喚醒,或者 BIOS 設置的不正確

內網穿透

做到現在這樣,我們已經完成了大部分工作,下面唯一要做的是如何從外網上訪問到這臺 openwrt 的設備,這就是前面說過的 內網穿透

搞內網穿透是需要在互聯網上有一臺服務器(VPS)的,可以是那種很便宜性能很弱的VPS,因為我們不干別的事,就是轉發一下數據而已;

我自己使用的是一臺俄羅斯的 VPS,價格只有 US$13.04/年,512M內存,5G的SSD,運行 ubuntu 20.04,雖然配置低,但是用起來感覺還是不錯的,我很樂意推薦給大家:

  • [俄羅斯VPS](https://justhost.ru/?ref=149230)

前面說過我使用的內網穿透的工具是一個開源項目,叫做 frp,項目地址如下:

  • [frp內網穿透項目](https://github.com/fatedier/frp)
  • 該項目有中文文檔,大家可以按照文檔下載適當的 release,其服務器軟件 frps 運行在服務器(VPS)上,客戶端 frpc 運行在 openwrt 上;
  • 通常服務器端軟件都是 64 位的 X86 架構,比較容易搞定;
  • 要注意的是,要看清楚運行 openwrt 的設備是什么架構,是 32 位的還是 64 位的,比如本文中的設備 CPU 為 S805,就是一個 32 位的 arm 架構,否則你下載的客戶端軟件可能無法運行;
  • 這個軟件的設置還是要費一些功夫,請認真閱讀該項目的文檔,并參考其范例;這里我給出我的實例

服務器端配置文件:frps.ini,其中的 xxx.xxx.xxx.xxx 請按照實際情況設置,frp_log_path 請指向實際存放 frp 日志的目錄

[common]
bind_addr = xxx.xxx.xxx.xxx
bind_port = 57000
bind_udp_port = 57001
kcp_bind_port = 57000
proxy_bind_addr = xxx.xxx.xxx.xxx
vhost_http_port = 58080
vhost_https_port = 58443

log_file = /frp_log_path/frps.log
log_level = info
log_max_days = 3
disable_log_color = false

detailed_errors_to_client = true

authentication_method = token
authenticate_heartbeats = false
authenticate_new_work_conns = false
token = skyline.admin

oidc_client_id =
oidc_client_secret = 
oidc_audience = 
oidc_token_endpoint_url = 

allow_ports = 58000-59000,50000-53000
max_pool_count = 15
max_ports_per_client = 0
tls_only = false
subdomain_host = frps.com
tcp_mux = true

客戶端配置文件:frpc.ini,其中的 xxx.xxx.xxx.xxx 請按照實際情況設置;openwrt.aaa.com 是一個 A 記錄指向 VPS 的域名(子域名),也要根據實際情況進行設置

[common]
server_addr=xxx.xxx.xxx.xxx
server_port=57000
log_file=/tmp/frpc.log
log_level=info
log_max_days=3
disable_log_color=false
token=skyline.admin
pool_count=5
tcp_mux=true
user=whowin
login_fail_exit=false
protocol=tcp
tls_enable=falset
DNS_server=8.8.8.8
admin_addr=127.0.0.1
admin_port=7400
admin_user=skyline
admin_pwd=admin

[ssh]
type=tcp
local_ip=192.168.2.100
local_port=22
use_encryption=false
use_compression=false
custom_domain=openwrt.aaa.com
remote_port=52998
health_check_type=tcp
health_check_timeout_s=3
health_check_max_failed=10
health_check_interval_s=30

[openwrt_web]
type=http
local_ip=192.168.2.100
local_port=80
use_encryption=false
use_compression=true
custom_domains=openwrt.aaa.com
header_X-From-Where=frp           
health_check_type=http    
health_check_url=/        
health_check_interval_s=90 
health_check_max_failed=3
health_check_timeout_s=3

啟動 VPS 上的 frpspath_to 指向實際路徑

/path_to/frps -c /path_to/frps.ini &

 

 

啟動 openwrt 上的 frpcpath_to 指向實際路徑

/path_to/frpc -c /path_to/frpc.ini &

 

 

如遇問題,強烈建議認真查看 frps.log 和 frpc.log

正常情況下,現在你已經可以在互聯網上通過 frp 訪問你家里的 openwrt 了,像這樣:

ssh [email protected] -p 52998

 

 

其中:xxx.xxx.xxx.xxx 為 VPS 的 IP 地址,52998 是在 frpc.ini 中設置的端口號,也可以設置一個域名指向 VPS 的 IP,比如設置 vps.aaa.com 的 A 記錄指向 VPS,則可以這樣登錄 openwrt

ssh [email protected] -p 52998

 

同樣,按照上面的設置,如果要訪問 openwrt 的 web 界面,在瀏覽器上輸入:openwrt.aaa.com:58080 即可,58080 是在 frps.ini 中設置的一個端口號;

特別要注意的是,要在 VPS 上設置好防火墻,放開可能用到的端口,否則 frp 將無法正常工作。

遠程開機測試

測試遠程開機使用的電腦、平板或者手機,不能連接到家里的 wifi 上,建議使用手機,關掉 wifi,打開 ConnectBot

設置連接如下:

圖16:在ConnectBot上設置連接

通過 *frp* 連接到 *openwrt*

圖17:在ConnectBot上連接openwrt

 

在 openwrt 上運行 wakeOnLan

圖18:在openwrt上運行wakeOnLan

正常情況下,MAC 地址指定的機器應該已經開機了;為了運行方便,你可以在 openwrt 上寫一個 shell 腳本,免得每次都要輸入 IP 地址和 MAC 地址,像下面這樣,注意,openwrt 下的 shell 是 ash

$ cat wakeOnLan.sh 
#!/bin/ash
/home/whowin/wakeOnLan 192.168.2.255 00:e0:2b:68:00:03 
$

7. 后記

前面提過,Magic Packet 可以在任意端口發送,通常使用端口 7 或 9,我們這個例子使用端口 7 發送,讀者可以試一下從其他端口發送,比如端口 1234;

實際上,openwrt 是有現成的網絡喚醒模塊的,可以在 openwrt 的 web 界面上搜索 luci-app-wol,安裝這個軟件的同時,還會安裝一個 etherwake 的軟件,安裝好以后,可以使用類似 etherwake -b AA:BB:CC:DD:EE:FF 的命令發送 Magic Packet 喚醒指定的機器,也可以通過 web 界面喚醒指定的電腦

圖19:在web界面上發送Magic Packet

至此,我們的這個項目就算做完了,我們基本上經歷了一個嵌入式開發的全過程,只是每一個階段都比較簡單而已,嵌入式開發,貌似復雜,其實并沒有想象的那么難;

在嵌入式項目的設計階段,我們需要有足夠的知識儲備以便為我們的需求提出最合理的方案,在這個項目的設計中,正是由于我們儲備了 Magic Packet 和反向代理的知識,才可以為我們的需求提出這樣一個軟硬件結合的方案;

我們這個項目基本沒有硬件開發,但是通常情況下,嵌入式開發的軟件工程師是需要參與到硬件開發中去的,包括芯片方案的選擇等都要參與意見,以便設計開發的硬件產品在今后的軟件開發中可以比較順利,所以嵌入式軟件工程師同樣要具備閱讀芯片的 datasheet 的能力和看懂硬件原理圖的能力,好的嵌入式軟件工程師也可以擁有非常不錯的焊接技能;

嵌入式開發的最關鍵的地方還是軟件開發,但比普通的軟件開發所要了解的知識要多很多,比如在我們這個項目中,我們必須要知道我們所用的硬件的 CPU 是什么,甚至要知道這個 CPU 的架構,否則,我們無法為這個硬件構建正確的操作系統,也無法在開發機上為這個硬件構建正確的交叉編譯環境;

如果你喜歡做嵌入式開發,希望這篇文章能給予你幫助。

最后歡迎訪問我的博客:https://whowin.gitee.io

分享到:
標簽:嵌入式
用戶無頭像

網友整理

注冊時間:

網站:5 個   小程序:0 個  文章:12 篇

  • 51998

    網站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會員

趕快注冊賬號,推廣您的網站吧!
最新入駐小程序

數獨大挑戰2018-06-03

數獨一種數學游戲,玩家需要根據9

答題星2018-06-03

您可以通過答題星輕松地創建試卷

全階人生考試2018-06-03

各種考試題,題庫,初中,高中,大學四六

運動步數有氧達人2018-06-03

記錄運動步數,積累氧氣值。還可偷

每日養生app2018-06-03

每日養生,天天健康

體育訓練成績評定2018-06-03

通用課目體育訓練成績評定