分類
發燒車訊

前端每周學習分享–第12期

1.VuePress

大家看過不少Vue.js及其子項目的文檔,一定發現了它們風格完全一致,界面清爽,讀起來很舒服,它們都使用了vuepress。

VuePress是尤大為了支持 Vue 及其子項目的文檔需求而寫的一個靜態網站生成工具,廣泛用於編寫技術文檔 ,可以部署在github上做個人博客。

原理:

在構建過程中,會創建應用程序的服務器渲染版本,通過訪問每個路由,來渲染相應的 HTML。

其中, 每個 markdown 文件都使用 編譯為 HTML,然後作為 Vue 組件的模板進行處理。這允許你直接在 markdown 文件中使用 Vue,在需要嵌入動態內容時,這種使用方式非常有用。

十分實用的特性:

  • md文件可內嵌vue代碼
  • 可自定義主題
  • 利用service worker做離線緩存
  • 多語言支持
  • 基於git的最近更新

官方文檔:

快速搭建:

2.WebWorker

web worker是運行在後台的jacvascript,利用類似線程的消息傳遞實現并行,獨立於其他腳本,不會影響頁面的性能。

web worker能夠長時間運行,有理想的啟動性能以及理想的內存消耗。

worker 創建后,它可以向它的創建者指定的事件監聽函數傳遞消息,這樣該worker生成的所有任務都會接收到這些消息。

webworker有專用線程dedicated worker(單窗口專用),sharedWorker(可多窗口共享),以及後來的service worker(目前瀏覽器支持程度還不高)。

2.1.dedicated worker

使用方法:

worker線程里監聽onmessage,

頁面線程里創建worker對象:const myworker = new Worker("worker.js")

發送消息:postMessage(msg)

接受消息:onmessage = function(e){const msg = e.data}

msg的數據格式自行定義。

終止worker:myworker.terminate()

例如下面的示例,worker會接收頁面上輸入的兩個数字,計算出乘積后返回結果。

worker.js

onmessage = function(e) {
  console.log('Worker: Message received from main script');
  let result = e.data[0] * e.data[1];
  if (isNaN(result)) {
    postMessage('Please write two numbers');
  } else {
    let workerResult = 'Result: ' + result;
    console.log('Worker: Posting message back to main script');
    postMessage(workerResult);
  }
}

index.html里

const first = document.querySelector('#number1');
const second = document.querySelector('#number2');
const result = document.querySelector('.result');
if (window.Worker) {
    const myWorker = new Worker("worker.js");

    first.onchange = function() {
      myWorker.postMessage([first.value, second.value]);
      console.log('Message posted to worker');
    }

    second.onchange = function() {
      myWorker.postMessage([first.value, second.value]);
      console.log('Message posted to worker');
    }

    myWorker.onmessage = function(e) {
        result.textContent = e.data;
        console.log('Message received from worker');
    }
} else {
    console.log('Your browser doesn\'t support web workers.')
}

2.2.shared worker

共享進程可以連接到多個不同的頁面,這些頁面必須屬於相同的域(相同的協議,主機以及端口)

在火狐中,共享進程不能在私有與公共文檔間進行共享。

SharedWorker.port返回一個MessagePort對象,用來進行通信和對共享進程進行控制。

創建共享進程對象:const myWorker = new SharedWorker("worker.js");

獲取端口:

發送消息:myWorker.port.postMessage(msg)

接收消息:myWorker.port.onmessage = function(e) {const msg = e.data}

worker線程獲取端口:onconnect = function(e) {const port = e.ports[0]}

啟動端口:port.start()

2.3.service worker

Service Worker 可以理解為一個介於客戶端和服務器之間的一個代理服務器 ,常用於做離線資源緩存

出於對安全問題的考慮,Service Worker 只能被使用在 https 或者本地的 localhost 環境下。

暫時沒有仔細學這塊,可以閱讀。

參考文章:

3.代碼相關

3.1.元素內文本垂直居中

已知元素高度的話,可以設置line-height:元素高度.

如果元素高度未知,就不能使用line-height了。

有人會想使用line-height:100%,會發現這是不行的,這個百分比是相對當前字體尺寸,而不是元素高度。

我使用了flex布局實現

    display: flex;
    align-items:center;
    justify-content:center;

還可以設置padding來使文本看起來垂直居中

padding: 50px 20px;

3.2.微信小程序自定義placeholder的隱藏時機

在一個searchBar組件中,有一個自定的placeholder如下:

<!-- <view
​        wx:if="{{!inputValue.length}}"
​        class="placeholder" >
​        {{placeholder}}
​     </view> -->

原生的placeholder不是在觸發bindinput時隱藏,而是在輸入鍵盤按鈕點擊時。使用inputValue.length來判斷显示自定義的placeholder會在某些輸入法中導致拼音預覽和自定義placeholder重疊(因為拼音显示的時候value值還沒變)

最後選擇棄用這個自定義placeholder,使用input組件的placeholder屬性,並使用placeholder-class來設置它的樣式。

3.3.關於微信小程序原生組件的坑

原生組件有camera、canvas、input (僅在focus時表現為原生組件) 、live-player、live-pusher、map、textarea、video、cover-view、cover-image。

所以當你用canvas畫圖表、使用地圖、播放視頻甚至做文本輸入時,都是可能遇到相關坑點的。

  1. 關於原生組件、組件之間的層級關係、

​ 原生組件的層級始終高於普通組件,不論普通組件的z-index設置了多少。

​ 后插入的原生組件可以覆蓋之前的原生組件。

​ 原生組件之間的相對層級關係可以通過z-index來調整。

​ 原生組件會遮擋vconsole彈出的調試面板。

​ cover-view和cover-image可以覆蓋在部分原生組件上。

  1. cover-view的使用

​ cover-view在做地圖、畫布、視頻上的彈出層時是會用到的,但它有很多使用限制。

​ cover-view只能內嵌cover-view、cover-image、button,其他元素在真機上就會被cover-view給覆蓋住,如果想內嵌radio、picker等就只能自己用這3個可內嵌的元素來實現。

​ cover-view不支持iconfont,也不支持單邊border、background-imageshadowoverflow: visible等。

  1. input的使用

​ input在不聚焦時是佔位元素,會被原生組件遮擋,聚焦時才使用原生組件渲染。這就會出現input設置了更高的z-index,不聚焦時仍會被其他原生組件遮住。

​ 要解決這個問題,可以使用textarea來代替input。

​ 我的一個解決方案是,加一個標誌位來記錄input是否聚焦,當不聚焦時,显示一個承載value值的cover-view(它需要綁定一個觸發聚焦的點擊事件),聚焦時,就显示input組件。

3.4.多個標籤頁之間的通信方案

  1. 使用websocket

  2. 使用localstorage或者cookie

  3. 使用sharedworker

我遇到的問題是需要在新窗口打開當前網站的新窗口時,能繼承上一個窗口的vuex的狀態樹里的某些數據。這不需要和服務器打交道,最好就在本地。

最後使用localstorage來做,在跳轉新窗口前更新localstorage,在新窗口根組件掛載時取出數據。

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理
【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

分類
發燒車訊

回聲消除中的LMS和NLMS算法與MATLAB實現

  自適應濾波是数字信號處理的核心技術之一,在科學和工業上有着廣泛的應用領域。自適應濾波技術應用廣泛,包括回波抵消、自適應均衡、自適應噪聲抵消和自適應波束形成。回聲對消是當今通信系統中普遍存在的現象。聲回波引起的信號干擾會分散用戶的注意力,降低通信質量。本文重點介紹了LMS和NLMS算法的使用,以減少這種不必要的回聲,從而提高通信質量

關鍵詞:自適應濾波器,自適應算法,回聲消除

1  引言

  當音頻信號在真實環境中產生混響時,就會產生聲學回聲,從而導致原始信號加上信號[1]的衰減、延時圖像。本文將重點研究通信系統中聲學回波的產生。

  自適應濾波器是一種動態濾波器,它不斷地改變其特性以獲得最優的輸出。自適應濾波算法通過改變參數使期望輸出d (n)與實際輸出y (n)之間的差值最小化。該函數稱為自適應算法的代價函數(loss)。圖1显示了自適應回聲抵消系統的框圖。其中,濾波器H(n)表示聲環境的脈衝響應,W(n)表示用來抵消回波信號的自適應濾波器。自適應濾波器的目標是使輸出的y(n)與期望的d(n)(在回聲環境中混響的信號)相等。在每次迭代中,誤差信號e(n)=d (n)-y (n)被反饋回濾波器,濾波器的特性也隨之改變。

自適應回聲消除系統

  自適應濾波器的目標是計算期望信號與自適應濾波器輸出之間的差值e(n)。該誤差信號反饋到自適應濾波器,並通過算法改變其係數,以最小化該差值的函數,即代價函數。在聲回波消除的情況下,自適應濾波器的最優輸出與不需要的回波信號等值。當自適應濾波器輸出等於期望信號時,誤差信號為零。在這種情況下,回顯信號將被完全取消,遠用戶將不會聽到他們的任何原始語音返回給他們。

2. 最小均方(LMS)算法

  最小均方(LMS)算法是由Widrow和Hoff在1959年通過對模式識別的研究首次提出的。由此成為自適應濾波中應用最廣泛的算法之一。LMS算法是一種基於隨機梯度的自適應濾波算法,它利用濾波器權重的梯度來收斂到最優的維納解[2-4]。由於其計算簡單而廣為人知並被廣泛使用。正是這種簡單性使它成為判斷所有其他自適應濾波算法的基準。

  隨着LMS算法的每次迭代,自適應濾波器的濾波抽頭(tap)權值按照如下公式進行更新。

$$公式1:w(n+1)=w(n)2\mu e(n)x(n)$$

  這裏x(n)是延時輸入值的輸入向量,$x(n)=[x_1(n)x_2(n)…x_N(n)]^T=[x(n)x(n-1)…x(n-N+1)]^T$。向量$w(n)=[w_0(n)w_1(n)w_2(n)…w_{N-1}(n)]^T$代表自適應FIR濾波器抽頭(tap)權向量在時刻n的係數。參數μ被稱為步長參數和小正的常數。此步長參數控制更新因子的影響。μ必須選擇一個合適的值LMS算法的性能,如果該值太小自適應濾波器的收斂時間會太長;如果μ太大自適應濾波器變得不穩定,導致其輸出發散[5 – 8]

2.1 LMS算法的實現

LMS算法的每次迭代都需要三個不同的步驟,順序如下:

1. FIR濾波器的輸出y(n)用公式2計算。

$$公式2:y(n)=\sum_{i=0}^{N-1}w(n)x(n-1)=w^T(n)x(n)$$

2. 誤差估計的值按公式3計算。

$$公式3:e(n)=d(n)-y(n)$$

3.更新FIR向量的抽頭tap權值,為下一次迭代做準備,如公式4所示。

$$公式4:w(n+1)=w(n)+2\mu e(n)x(n)$$

  LMS算法在自適應濾波中得到廣泛應用的主要原因是其計算簡單,比其他常用的自適應算法更易於實現。LMS算法每次迭代需要2N加法和2N + 1次乘法(N用於計算輸出y(N)),另一個用於通過向量乘法計算標量[9]

clear;
clc;
snr=20;     % 信噪比
order=8;    % 自適應濾波器的階數為8
Hn =[0.8783 -0.5806 0.6537 -0.3223 0.6577 -0.0582 0.2895 -0.2710 0.1278 ...     % ...表示換行的意思
    -0.1508 0.0238 -0.1814 0.2519 -0.0396 0.0423 -0.0152 0.1664 -0.0245 ...
    0.1463 -0.0770 0.1304 -0.0148 0.0054 -0.0381 0.0374 -0.0329 0.0313 ...
    -0.0253 0.0552 -0.0369 0.0479 -0.0073 0.0305 -0.0138 0.0152 -0.0012 ...
    0.0154 -0.0092 0.0177 -0.0161 0.0070 -0.0042 0.0051 -0.0131 0.0059 ...
    -0.0041 0.0077 -0.0034 0.0074 -0.0014 0.0025 -0.0056 0.0028 -0.0005 ...
    0.0033 -0.0000 0.0022 -0.0032 0.0012 -0.0020 0.0017 -0.0022 0.0004 -0.0011 0 0];
Hn=Hn(1:order);
mu=0.5;             % mu表示步長
N=1000;             % 橫坐標1000個採樣點
Loop=150;           % 150次循環
EE_NLMS=zeros(N,1); % 不同步長的初始化誤差
for nn=1:Loop       % epoch=150
    % 權重初始化w
    win_NLMS=zeros(1,order);         % NLMS四種步長測試,四個權重——1
    error_NLMS=zeros(1,N)';     % 初始化誤差
    % 均勻分佈的輸入值
    r=sign(rand(N,1)-0.5);          % shape=(1000,1)的(0,1)均勻分佈-0.5,sign(n)>0=1;<0=-1
    % 輸出:輸入卷積Hn得到 輸出
    output=conv(r,Hn);              % r卷積Hn,output長度=length(u)+length(v)-1
    output=awgn(output,snr,'measured');     % 將白高斯噪聲添加到信號中

    % N=1000,每個採樣點
    for i=order:N         % i=81000
      input=r(i:-1:i-order+1);  % 每次迭代取8個數據進行處理
      e_NLMS = output(i)-win_NLMS*input;
      win_NLMS=win_NLMS+e_NLMS*input'/(input'*input);   % NLMS更新權重
      error_NLMS(i)=error_NLMS(i)+e_NLMS^2;
    end
    
    EE_NLMS=EE_NLMS+error_NLMS;     % 把總誤差相加
end
% 對總誤差求平均值
error_NLMS=EE_NLMS/Loop;

figure;
error_NLMS=10*log10(error_NLMS(order:N));
plot(error_NLMS,'r');       % 紅色
axis tight;                 % 使用緊湊的坐標軸
legend('NLMS算法');           % 圖例
title('NLMS算法誤差曲線');     % 圖標題
xlabel('樣本');                     % x軸標籤
ylabel('誤差/dB');                  % y軸標籤
grid on;                            % 網格線

3 歸一化最小均方(NLMS)算法

  LMS算法的主要缺點之一是每次迭代都有一個固定的步長參數。這需要在開始自適應濾波操作之前了解輸入信號的統計信息。實際上,這是很難實現的。即使我們假設自適應回聲抵消系統的唯一輸入信號是語音,但仍有許多因素如信號輸入功率和振幅會影響其性能[10-12]

  歸一化最小均方算法(NLMS)是LMS算法的擴展,LMS算法通過計算最大步長值來繞過這個問題。步長值的計算公式如下

$$Step\ size = \frac{1}{dot\ product(input\ vector,\ input\ vector)}$$

這個步長與輸入向量x(n)的係數的瞬時值的總期望能量的倒數成正比。輸入樣本的期望能量之和也等於輸入向量與自身的點積,以及輸入向量自相關矩陣的跡R[13-15]。

$$公式5:tr[R]=\sum_{i=0}^{N-1}E[x^2(n-i)]\\ \quad\quad =E[\sum_{i=0}^{N-1}x^2(n-i)]$$

NLMS算法的遞歸公式如式6所示

$$公式6:w(n+1)=w(n)+\frac{1}{x^T(n)x(n)}e(n)x(n)$$

3.1 NLMS算法的實現

  NLMS算法已在Matlab中實現。由於步長參數是根據當前的輸入值來選擇的,因此NLMS算法在未知信號下具有更大的穩定性。該算法具有良好的收斂速度和相對簡單的計算能力,是實時自適應回波抵消系統[16]的理想算法

  由於NLMS是標準LMS算法的擴展,因此NLMS算法的實際實現與LMS算法非常相似。NLMS算法的每次迭代都需要按照以下順序執行這些步驟。

1. 計算了自適應濾波器的輸出

$$公式7:y(n)=\sum_{i=0}^{N-1}w(n)x(n-i)=w^T(n)x(n)$$

2. 誤差信號等於期望信號和濾波器輸出之間的差值。

$$公式8:e(n)=d(n)-y(n)$$

3.計算了輸入向量的步長值。

$$公式9:\mu(n)=\frac{1}{x^T(n)x(n)}$$

4. 濾波器抽頭權重更新,為下一次迭代做準備。

$$公式10:w(n+1)=w(n)+\mu(n)e(n)x(n)$$

NLMS算法的每次迭代都需要3N+1次乘法,僅比標準LMS算法多N次。考慮到所獲得的穩定性和回波衰減增益,這是一個可接受的增加。

clear;
clc;
snr=20;     % 信噪比
order=8;    % 自適應濾波器的階數為8
% Hn是濾波器權重
Hn =[0.8783 -0.5806 0.6537 -0.3223 0.6577 -0.0582 0.2895 -0.2710 0.1278 ...     % ...表示換行的意思
    -0.1508 0.0238 -0.1814 0.2519 -0.0396 0.0423 -0.0152 0.1664 -0.0245 ...
    0.1463 -0.0770 0.1304 -0.0148 0.0054 -0.0381 0.0374 -0.0329 0.0313 ...
    -0.0253 0.0552 -0.0369 0.0479 -0.0073 0.0305 -0.0138 0.0152 -0.0012 ...
    0.0154 -0.0092 0.0177 -0.0161 0.0070 -0.0042 0.0051 -0.0131 0.0059 ...
    -0.0041 0.0077 -0.0034 0.0074 -0.0014 0.0025 -0.0056 0.0028 -0.0005 ...
    0.0033 -0.0000 0.0022 -0.0032 0.0012 -0.0020 0.0017 -0.0022 0.0004 -0.0011 0 0];
Hn=Hn(1:order);
mu=0.5;             % mu表示步長
N=1000;             % 橫坐標1000個採樣點
Loop=150;           % 150次循環
% 不同步長的初始化誤差
EE_LMS = zeros(N,1);
EE_NLMS=zeros(N,1);
for nn=1:Loop       % epoch=150
    win_LMS = zeros(1,order);   % 權重初始化w
    error_LMS=zeros(1,N)';      % 初始化誤差
    % 均勻分佈的語音數據輸入
    r=sign(rand(N,1)-0.5);          % shape=(1000,1)的(0,1)均勻分佈-0.5,sign(n)>0=1;<0=-1
    % 輸出:輸入卷積Hn得到 輸出
    output=conv(r,Hn);              % r卷積Hn,output長度=length(u)+length(v)-1
    output=awgn(output,snr,'measured');     % 真實輸出=將白高斯噪聲添加到信號中

    % N=1000,每個採樣點
    for i=order:N         % i=81000
      input=r(i:-1:i-order+1);  % 每次迭代取8個數據進行處理
      e_LMS = output(i)-win_LMS*input;
      
      mu=0.02;      % 步長
      win_LMS = win_LMS+2*mu*e_LMS*input';
      error_LMS(i)=error_LMS(i)+e_LMS^2;
    end
    % 把總誤差相加
    EE_LMS = EE_LMS+error_LMS;

end
% 對總誤差求平均值
error_LMS = EE_LMS/Loop;

figure;
error1_LMS=10*log10(error_LMS(order:N));
plot(error1_LMS,'b.');  % 藍色
axis tight;         % 使用緊湊的坐標軸
legend('LMS算法');       % 圖例
title('LMS算法誤差曲線');  % 圖標題
xlabel('樣本');                     % x軸標籤
ylabel('誤差/dB');                  % y軸標籤
grid on;                            % 網格線

4 LMS算法的結果

  利用Matlab對LMS算法進行了仿真。圖2显示的是通過麥克風從計算機系統收集到的輸入語音信號。圖3显示了從輸入信號派生出的所需回波信號。圖4显示了自適應濾波器的輸出,它將減少輸入信號的回波信號。圖5显示了由濾波器輸出信號計算出的均方誤差信號。圖6是由回波信號對誤差信號的分割得到的衰減。

  自適應濾波器為1025階FIR濾波器。步長設置為0.02。MSE表明,隨着算法的發展,代價函數的平均值逐漸減小。

5 NLMS算法的結果

  用Matlab對NLMS算法進行了仿真。圖7显示了輸入信號。圖8显示了所需的信號。圖9显示了自適應濾波器輸出。圖10显示了均方誤差。圖11显示了衰減。

  自適應濾波器為1025階FIR濾波器。步長設置為0.1。

 

 NLMS算法在均方誤差和平均衰減方面優於LMS算法,其性能總結如表1所示。

 

6 結論

  由於其簡單性,LMS算法是最流行的自適應算法。然而,LMS算法存在收斂速度慢和數據依賴的問題。

  NLMS算法是LMS算法的一個同樣簡單但更健壯的變體,它在簡單性和性能之間表現出比LMS算法更好的平衡。由於其良好的性能,NLMS在實時應用中得到了廣泛的應用。

7. 參考

文章翻譯自論文《2011_adaptive algorithms for acoustic echo cancellation in speech processing》

[1]. Homana, I.; Topa, M.D.; Kirei, B.S.; “Echo cancelling using adaptive algorithms”, Design and Technology of Electronics Packages, (SIITME) 15th International Symposium., pp. 317-321, Sept.2009.

[2]. Paleologu, C.; Benesty, J.; Grant, S.L.; Osterwise, C.; “Variable step-size NLMS algorithms for echo cancellation” 2009 Conference Record of the forty-third Asilomar Conference on Signals, Systems and Computers., pp. 633-637, Nov 2009.

[3]. Soria, E.; Calpe, J.; Chambers, J.; Martinez, M.; Camps, G.; Guerrero, J.D.M.; “A novel approach to introducing adaptive filters based on the LMS algorithm and its variants”, IEEE Transactions, vol. 47, pp. 127-133, Feb 2008.

[4]. Tandon, A.; Ahmad, M.O.; Swamy, M.N.S.; “An efficient, low-complexity, normalized LMS algorithm for echo cancellation”, IEEE workshop on Circuits and Systems, 2004. NEWCAS 2004, pp. 161-164, June 2004.

[5]. Eneman, K.; Moonen, M.; “Iterated partitioned block frequency-domain adaptive filtering for acoustic echo cancellation,” IEEE Transactions on Speech and Audio Processing, vol. 11, pp. 143-158, March 2003.

[6]. Krishna, E.H.; Raghuram, M.; Madhav, K.V; Reddy, K.A; “Acoustic echo cancellation using a computationally efficient transform domain LMS adaptive filter,” 2010 10th International Conference on Information sciences signal processing and their applications (ISSPA), pp. 409-412, May 2010.

[7]. Lee, K.A.; Gan,W.S; “Improving convergence of the NLMS algorithm using constrained subband updates,” Signal Processing Letters IEEE, vol. 11, pp. 736-739, Sept. 2004.

[8]. S.C. Douglas, “Adaptive Filters Employing Partial Updates,” IEEE Trans.Circuits SYS.II, vol. 44, pp. 209-216, Mar 1997.

[9]. D.L. Duttweiler, “Proportionate Normalized Least Mean Square Adaptation in Echo Cancellers,” IEEE Trans. Speech Audio Processing, vol. 8, pp. 508-518, Sept. 2000.

[10]. E. Soria, J. Calpe, J. Guerrero, M. Martínez, and J. Espí, “An easy demonstration of the optimum value of the adaptation constant in the LMS algorithm,” IEEE Trans. Educ., vol. 41, pp. 83, Feb. 1998.

[11]. D. Morgan and S. Kratzer, “On a class of computationally efficient rapidly converging, generalized NLMS algorithms,” IEEE Signal Processing Lett., vol. 3, pp. 245–247, Aug. 1996.

[12]. G. Egelmeers, P. Sommen, and J. de Boer, “Realization of an acoustic echo canceller on a single DSP,” in Proc. Eur. Signal Processing Conf. (EUSIPCO96), Trieste, Italy, pp. 33–36, Sept. 1996.

[13]. J. Shynk, “Frequency-domain and multirate adaptive filtering,” IEEE Signal Processing Mag., vol. 9, pp. 15– 37, Jan. 1992.

[14]. Ahmed I. Sulyman and Azzedine Zerguine, “Echo Cancellation Using a Variable Step-Size NLMS Algorithm”, Electrical and Computer Engineering Department Queen’s University.

[15]. D. L. Duttweiler, “A twelve-channel digital echo canceller,” IEEE Trans. Commun., vol. 26, no. 5, pp. 647–653, May 1978.

[16]. J. Benesty, H. Rey, L. Rey Vega, and S. Tressens, “A nonparametric VSS NLMS algorithm,” IEEE Signal Process. Lett., vol. 13, pp. 581–584, Oct. 2006.

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

大陸寄台灣空運注意事項

大陸海運台灣交貨時間多久?

※避免吃悶虧無故遭抬價!台中搬家公司免費估價,有契約讓您安心有保障!

分類
發燒車訊

中國汽車工業三十強榜單發佈:冠軍上汽集團營收超萬億元

2016年5月26日,中國機械工業聯合會、中國汽車工業協會發佈最新中國汽車工業三十強榜單。上汽集團以2015年1.2萬億元的總營業收入繼續蟬聯冠軍,一汽和東風依然排第2、3位。

榜單中,蓋世汽車盤點出有乘用車公司16家,商用車公司4家,零部件公司7家,摩托車公司3家。本次榜單基於“年度匯總口徑快報”統計2015年營業收入,和上市公司合併財務報表中的營業收入存在計算上的差別,後者抵消了關聯交易部分。這也是為何上汽2015年年報中營收為670,448,223,139.34元,而本榜單中為1.2萬億元的緣故。

對比2015年排名(以2014年營業收入統計),19家企業排名沒有變化,比亞迪和威孚高科新上榜,陝西汽車和金城集團落榜。前十名中,僅長城(今年第9)和重汽(今年第10)互換了名次,其他8家企業都保持了去年的座次。提升最快的是中鼎,從第27提高到第24,上升3位。下降幅度最大的是法士特,從第24滑落至第28。

冠軍上汽集團去年營收總額超過第2名一汽和第3名東風總和。

以下是具體排名

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

※專營大陸快遞台灣服務

台灣快遞大陸的貨運公司有哪些呢?

分類
發燒車訊

菲亞特董事長公開闢謠 廣汽入主消息不實

據《歐洲汽車新聞》報導,菲亞特克萊斯勒公司(FCA)董事長約翰•埃爾坎(John Elkann)明確指出,未與中國廣汽集團簽訂股權出售協定。

2015年FCA與廣汽延續廣汽菲亞特的合作關係,成立了廣汽菲克合資公司,投產Jeep自由光和自由俠。近日,《義大利日報》發佈了一篇爆料新聞,除在生產方面的合作外,廣汽集團還有意入主FCA,展開資本層面的聯姻。

埃爾坎同時也是菲亞特控股集團EXOR的董事長,25日召開了Exor股東大會。針對《義大利日報》的爆料,埃爾坎當日公開闢謠,公司與廣汽集團未簽訂股權出售協定。

埃爾坎也被詢問標緻雪鐵龍集團(PSA集團)是否可成為FCA的良好合作夥伴,該董事長則指出其公司正在尋求的推動轉型的合作夥伴,PSA並不在公司的考慮範圍內。

據法國《回聲報》的報導,法國政府正在考慮出售其持有的PSA 14%的部分或全部股權。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

分類
發燒車訊

大眾汽車計畫投資100億歐元新建一座電池工廠

據外媒報導,大眾汽車計畫投資100億歐元新建一座電池工廠,意欲轉型為一家領先的電動汽車製造商,從而使其可以自己掌控電動汽車的命運,而不是單純依賴于亞洲的電池廠商。

在大眾汽車6月22日召開年度股東大會以前,該公司的一個非執行理事會將對首席執行官馬蒂亞斯•穆勒(Matthias Müller)及其下屬一個團隊提出的計畫進行考慮。根據《商報》的報導,這項計畫的規模將需要足夠大到可以支援一個目標,即在未來十年時間裡將純電動汽車(PEV)的銷售量提高至100萬輛。

從投資額來看,大眾汽車計畫建設的這座工廠類似於特斯拉汽車的“超級工廠”(Gigafactry),而該公司所需電池的規模也意味著這將是一座龐大的工廠,但大眾汽車尚未透露更多細節。

據報導,大眾汽車的董事會很可能將會批准這項計畫,而身為該公司大股東之一的德國下薩克森州(Lower Saxony)也將支持該計畫。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

※專營大陸快遞台灣服務

台灣快遞大陸的貨運公司有哪些呢?

分類
發燒車訊

大眾計畫為高端車型開發第二個電動汽車平臺

據外媒報導稱,大眾正在考慮開發第二個電動汽車平臺,用於更大、更高端的車型。

大眾的第一個電動汽車平臺名叫MEB,曾在CES上展示 過,BUDD-e概念車就是用該平臺開發的。該平臺專門針對小型汽車、輕型商務用車,充電一次行駛距離大約155英里至310英里(250-500公 裡)。目前大眾正在調查MEB平臺的彈性,看它是否可以用在高端車型上,比如Phaeton(輝騰),未來大眾可能會為高端車型專門開發一個新平臺。

按照大眾的計畫,2019年之前MEB平臺準備就緒,因為該平臺主要針對的是電動汽車,擴展性更強。也就是說汽車製造商調整軸距、軌距、座位位置更加容易一些,它們可以將平臺用在更多的車型上。落地式電池尤其引人注目,因為工程師可以根據車型改變電池的大小。

大眾集團電子研發主管沃克馬•坦尼伯格(Volkmar Tanneberger)稱,‘巧克力電池’(chocolate battery)製造更容易,可以進行大規模工業化生產。MEB能夠用在所有車型上,包括超小型Polo和中型汽車帕薩特(Passat),未來MEB有可能會成為大眾所有產品線的基石。如果MEB架構無法用在更大型的汽車上,比如輝騰,開發第二個電動汽車平臺就會變得有意義。保時捷Mission E和奧迪e-tron Quattro將會擁有自己的平臺,因為早在MEB架構公佈之前,它們已經設計成型。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

分類
發燒車訊

北汽規劃打造四大海外基地 南非新工廠將投產

據媒體報導,從北汽集團官方獲悉,北汽將斥資50億元在南非建設總裝 廠,該工廠擬於下月開始建設,計畫於2017年11月建成投產。按照規劃,北汽將打造包括南非、伊朗在內的四大海外運營基地並輻射周邊市場,形成四大屬地化產業運營集團。

未來北汽將海外市場拓展劃分了三條線,歸納為“一帶一路一洲 哥倫布航線”,其中“一帶一路”符合大環境下的海外發展趨勢,“一洲”則是“一帶一路”中涉及到的非洲,在此基礎上,北汽增加了“哥倫布航線”沿途的中南美地區。繼續細化,北汽將以“南非、伊朗、東南亞、墨西哥”四大重點專案為引領,建設輻射周邊市場的四大海外運營基地,逐步實現從“旅行者”到“定居者”的角色轉變。

與跨國車企在中國的發展要尋求本地車企進行合作類似,北汽在南非新建的工廠將由北汽集團與南非工業開發公司的合資企業負責運營。新工廠總投資金額達到50億元(7.73億美元),計畫於下月開始建設,有望於2017年11月建成投產,計畫年產能為10萬輛。

據介紹,南非工廠將作為試點,為後續北汽加速海外涉及12個國家的19個KD(散件組裝廠)專案建設積累經驗。北汽集團已於2013年在南非開設了一家小型SKD廠,位於斯普林斯鎮,該廠生產小型麵包計程車,此次在南非斥鉅資打造新工廠並作為試點也就不難理解。

北京汽車國際發展公司擁有五大核心業務,包括自主品牌整車和零部件產品的出口,技術、設備、整車的進口,此外還有產品改裝,境外投資以及國際合作,初期投放海外市場的產品也將以北汽自主品牌為主。這意味著即將建成的南非汽車生產廠將有望投產包括北京紳寶、北京牌和北汽威旺三大產品系列,初步形成對當地市場佈局的同時還將進行他國出口,擴大南非及周邊國家和地區市場份額。

在北汽擴大海外市場佈局後,未來市場銷量將成為企業諸多努力的體現。“十三五”期間北汽制定了“2030”戰略,戰略中指出企業要在2020年實現20萬輛整車出口,完成3個建設,包括國際化運營隊伍建設、合作夥伴隊伍建設、體系能力建設,從而實現品牌高端市場的突破。

本站聲明:網站內容來源於EnergyTrend https://www.energytrend.com.tw/ev/,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※如何讓商品強力曝光呢? 網頁設計公司幫您建置最吸引人的網站,提高曝光率!!

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

大陸寄台灣空運注意事項

大陸海運台灣交貨時間多久?

分類
發燒車訊

三、netcore跨平台之 Linux配置nginx負載均衡

前面兩章講了netcore在linux上部署以及配置nginx,並讓nginx代理webapi。

這一章主要講如何配置負載均衡,有些步驟在前兩章講的很詳細了,所以這一章我就不會一個個截圖了。

因為本人只有一個服務器。所以我會在同一台服務器上部署兩套差不多的實例。

同樣的代碼,我們在Program.cs進行了修改,如圖所示:

這裏我把原來的端口6666改成了8888

 

 然後你可以改一改你的接口部分的代碼,便於讓你更好的看到效果。

這裏把value1和value2改成value3和value4,這裡是為了看到測試效果,在實際的開發中這裏不用改。

 

 然後發布和上傳到服務器,如何發布和上傳,我在第一章有講到:https://www.cnblogs.com/dengbo/p/11878766.html

注意的是你同樣的地方新建一個新的目錄保存你新上傳的程序,netcore是我第一章建立的,netcore1是新建的,

你把你新的發布包放在netcore即可。如圖:

上傳結束后,在這個目錄中運行你的程序,輸入下面的命令

dotnet WebApiTest.dll   --server.urls "http://*:8888"

如圖所示

 

 然後去看看你的接口是否正常

 

 

好了,這裏的準備工作完成了,下面我們進入到nginx的配置的目錄中

輸入下面的命令:

cd /usr/local/nginx/conf

然後對文件進行編輯

vim nginx.conf

 

 我們需要在這裏修改一下配置。

在如圖的server的平級添加如下的代碼

upstream NgWebApi {
                server localhost:6666;
                server localhost:8888;
    }

上面的 NgWebApi是隨意寫的名稱,不要糾結這裏。

然後在修改 proxy_pass後面的內容:

proxy_pass http://NgWebApi;

最終的結果如下:

 

 這樣你就修改完成,輸入:wq退出並保存即可。

最後檢查並重啟nginx

/usr/local/nginx/sbin/nginx -t
/usr/local/nginx/sbin/nginx -s reload

最後不要忘記把你的8888端口的webapi啟動一下。

這裏我務必要提醒你,請進入到你的程序的目錄中執行這段代碼,

cd /root/netcore1
dotnet WebApiTest.dll   --server.urls "http://*:8888"

啟動如下:

 

 

 好了,配置結束了,下面我們來測試下

 

還是昨天的那個網站進行測試   https://www.sojson.com/httpRequest/

 

 

 

多次發送請求會出現下面的響應

 

 

看到上面兩個請求,就說明你配置成功了,是不是很簡單。

上面這種配置,系統會採用默認的輪詢訪問不同的端口,nginx作為強大的反向代理,強大的遠遠不止這裏

下面簡單講講分發策略。

1)、輪詢 ——輪流處理請求(這是系統默認的)

      每個請求按時間順序逐一分配到不同的應用服務器,如果應用服務器down掉,自動剔除它,剩下的繼續輪詢,如果您的服務器都差不多,建議這個。 

2)、權重 ——誰的設置的大,誰就承擔大部分的請求

      通過配置權重,指定輪詢幾率,權重和訪問比率成正比,用於應用服務器性能不均的情況,有時候你買的服務器可能參差不齊,有的性能強大

    有的一般,你可以通過設置權重,把服務器性能強大權重設置大一點,這樣可以合理分配壓力。 

3)ip_哈希算法

      每一次的請求按訪問iphash結果分配,這樣每個訪客固定訪問一個應用服務器,可以解決session共享的問題。

 

 

關於權重的策略,如下圖示的 你只要加一個  weight=6 即可這裏不一定是6,是整數都行。

 

 

 然後保存即可

這裏不要忘記重啟nginx,以及運行8888端口的程序了,如果你不會,可以看前面的部分

最後我們看看效果

結果和上面的測試結果差不多,唯一不同的是出現下面這個結果的次數要大於另外一個的。

 

 

到這裏就結束了,感謝觀看。

 

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※為什麼 USB CONNECTOR 是電子產業重要的元件?

網頁設計一頭霧水??該從何著手呢? 找到專業技術的網頁設計公司,幫您輕鬆架站!

※想要讓你的商品成為最夯、最多人討論的話題?網頁設計公司讓你強力曝光

※想知道最厲害的台北網頁設計公司推薦台中網頁設計公司推薦專業設計師”嚨底家”!!

※專營大陸快遞台灣服務

台灣快遞大陸的貨運公司有哪些呢?

分類
發燒車訊

利用SSH隧道技術穿越內網訪問遠程設備

本文為作者原創,轉載請註明出處:

通常,我們用於調試的計算機無法遠程訪問位於局域網中的待調試設備。通過 ssh 的端口轉發(又稱 ssh 隧道)技術,可以實現這種遠程調試功能。

下文中,sshc 指 ssh 客戶端,sshd 指 ssh 服務器。

1. ssh 端口轉發模式簡介

ssh 客戶端運行於本地機器,它的作用是:登錄到目標機器並在目標機器上執行命令。它可以建立一個安全通道,為不安全網絡上兩個不受信任的主機提供安全的加密通信。X11 連接、任意 TCP 端口和 UNIX 域套接字也可以通過 ssh 安全通道進行轉發。

ssh 連接並登錄到指定的主機名(用戶名可選)。如果指定了命令,命令將在遠程主機上執行,而不是在本機 shell 里執行。

1.1 ssh 常用選項簡介

ssh 端口轉發相關的常用選項如下:

-C

請求壓縮所有數據(包括 stdin、stdout、stderr 和用於轉發的 X11、TCP 和 UNIX 域連接的數據)。壓縮算法與 gzip 使用的算法相同,壓縮級別由 ssh 協議版本 1 的 CompressionLevel 選項控制。在調製解調器線路和其他慢速連接上採用壓縮是可取的,但它會減慢快速網絡上的速度。

-f

請求 ssh 在執行命令之前轉到後台。如果用戶希望 ssh 在後台運行,但 ssh 需要用戶提供密碼或口令,使用 -f 選項就很有用,在用戶輸入密碼之後,ssh 就會轉入後台運行。這個選項隱含了 -n 選項的功能(-n 選項將 stdin 重定向到 /dev/null,從而避免後台進程讀 stdin)。在遠程站點上啟動 X11 程序的推薦方法是使用 “ssh -f host xterm” 。

如果 ExitOnForwardFailure 配置選項設置的是 “yes”,則使用 -f 選項啟動的 ssh 客戶端會等所有的遠程端口轉發建立成功后才將自己轉到後台運行。

-n

將 stdin 重定向到 /dev/null (實際上是為了防止後台進程從stdin讀取數據)。當 ssh 在後台運行時必須使用此選項。

一個常見的技巧是使用它在目標機器上運行 X11 程序。例如,ssh -n shadow.cs.hut.fi emacs & 將在 shadows.cs.hut.fi 上啟動 emacs 程序。X11 的連接將通過加密通道自動轉發。ssh 程序將在後台運行。(如果 ssh 需要請求密碼或口令,則此操作無效;參見-f選項。)

-N

不執行遠程命令。此選項用於只需要端口轉發功能時。

-g

允許遠程主機連接到本地轉發端口。如果用於多路復用連接,則必須在主進程上指定此選項。

-t

強制分配一個偽終端。在目標機上執行任意的基於屏幕的程序時(例如,實現菜單服務),分配偽終端很有用。使用多個 -t 選項則會強制分配終端,即使 ssh 沒有本地終端。

-T

禁止分配偽終端。

-L [bind_address:]port:host:hostport
-L [bind_address:]port:remote_socket
-L local_socket:host:hostport
-L local_socket:remote_socket

數據從本機轉發到遠程。本機上指定 TCP 端口或 UNIX 套接字的連接將被轉發到目標機上指定端口或套接字。

上述參數中,bind_address 指本地地址;port 指本地端口;local_socket 指本地 UNIX 套接字;host 指遠程主機地址;hostport 指遠程端口;remote_socket 指遠程 UNIX 套接字。

本地(ssh 客戶端)與遠程(ssh 服務端)建立一條連接,此連接的形式有四種:

本地 [bind_address:]port    <====>   遠程 host:hostport  
本地 [bind_address:]port    <====>   遠程 remote_socket  
本地 local_socket           <====>   遠程 host:hostport  
本地 local_socket           <====>   遠程 remote_socket  

位於本機的 ssh 客戶端會分配一個套接字來監聽本地 TCP 端口(port),此套接字可綁定本機地址(bind_address, 可選,本機不同網卡具有不同的 IP 地址)或本地 UNIX 套接字(local_socket)。每當一個連接建立於本地端口或本地套接字時,此連接就會通過安全通道進行轉發。

也可在配置文件中設置端口轉發功能。只有超級用戶可以轉發特權端口。

默認情況下,本地端口是根據 GatewayPorts 設置選項綁定的。但是,使用顯式的bind_address 可將連接綁定到指定地址。bind_address 值是 “localhost”時,表示僅監聽本機內部數據[TODO: 待驗證],值為空或“*”時,表示監聽本機所有網卡的監聽端口。

注意:localhost 是個域名,不是地址,它可以被配置為任意的 IP 地址,不過通常情況下都指向 127.0.0.1(ipv4)和 。127.0.0.1 這個地址通常分配給 loopback 接口。loopback 是一個特殊的網絡接口(可理解成虛擬網卡),用於本機中各個應用之間的網絡交互。

GatewayPorts 說明 (查閱 man sshd_config):指定是否允許遠程主機(ssh客戶端)連接到本機(ssh服務端)轉發端口。默認情況下,sshd(8)將遠程端口轉發綁定到環回地址,這將阻止其他遠程主機連接到本機轉發端口。GatewayPorts 也可設置為將將遠程端口轉發綁定到非環回地址,從而允許其他遠程主機連接到本機。GatewayPorts 值“no”,表示強制遠程端口轉發僅對本機可用;值“yes”,表示強制遠程端口轉發綁定到通配符地址;值“clientspecified”,表示允許客戶端選擇轉發綁定到的地址。默認是“no”。

-R [bind_address:]port:host:hostport
-R [bind_address:]port:local_socket
-R remote_socket:host:hostport
-R remote_socket:local_socket

此選項在本地機上執行,目標機上指定 TCP 端口或 UNIX 套接字的連接將被轉發到本機上指定端口或套接字。

上述參數中,bind_address 指遠程地址;port 指遠程端口;remote_socket 指遠程 UNIX 套接字;host 指本地地址;hostport 指本地端口;local_socket 指本地 UNIX 套接字。

工作原理:位於遠程的 ssh 服務端會分配一個套接字來監聽 TCP 端口或 UNIX 套接字。當目標機(服務端)上有新的連接建立時,此連接會通過安全通道進行轉發,本地機執行當前命令的進程收到此轉發的連接后,會在本機內部新建一條 ssh 連接,連接到當前選項中指定的端口或套接字。參 2.3 節分析。

也可在配置文件中設置端口轉發功能。只有超級用戶可以轉發特權端口。

默認情況下,目標機(服務端)上的 TCP 監聽套接字只綁定迴環接口。也可將目標機上的監聽套接字綁定指定的 bind_address 地址。bind_address 值為空或 “*” 時,表示目標機上的監聽套接字會監聽目標機上的所有網絡接口。僅當目標機上 GatewayPorts 設置選項使能時,通過此選項為目標機指定 bind_address 才能綁定成功(參考 sshd_config(5))。

如果 port 參數是 ‘0’,目標機(服務端)可在運行時動態分配監聽端口並通知本地機(客戶端),如果同時指定了 “-O forward” 選項,則動態分配的監聽端口會被打印在標準輸出上。

-D [bind_address:]port

指定本地“動態”應用程序級端口轉發。它的工作方式是分配一個套接字來監聽本地端口(可選綁定指定的 bind_address)。每當連接到此端口時,連接都通過安全通道進行轉發,然後使用應用程序協議確定將遠程計算機連接到何處。目前支持 SOCKS4 和 SOCKS5 協議,ssh 將充當 SOCKS 服務器。只有 root 用戶可以轉發特權端口。還可以在配置文件中指定動態端口轉發。

IPv6 地址可以通過將地址括在方括號中來指定。只有超級用戶可以轉發特權端口。默認情況下,本地端口是根據 GatewayPorts 設置選項進行綁定的。但是,可以使用顯式的 bind_address 將連接綁定到特定的地址。bind_address 值為 “localhost” 時表示監聽端口僅綁定為本地使用,而空地址或 “*” 表示監聽所有網絡接口的此端口。

1.2 ssh 端口轉發模式

ssh 的端口轉發有三種模式:

  • 本地:ssh -C -f -N -g -L local_listen_port:remote_host:remote_port agent_user@agent_host

    將本地機監聽端口 local_listen_port 上的數據轉發到遠程端口 remote_host:remote_port

  • 遠程:ssh -C -f -N -g -R agent_listen_port:local_host:local_port agent_user@agent_host

    將代理機監聽端口 agent_listen_port 上的數據轉發到本地端口 local_host:local_port

  • 動態:ssh -C -f -N -g -D listen_port agent_user@agent_host

2. 利用 ssh 隧道建立遠程調試環境

組網環境下設備角色如下:

代理機:把一個具有公網 IP 的中間服務器用作 ssh 代理,將這台代理機稱作代理 A(Agent)。

目標機:把待調試的目標機器稱作目標機 T(Target)。目標機通常是待調試的設備,處於局域網內,外網無法直接訪問內網中的設備。

本地機:把調試用的本地計算機稱作本地機 L(Local)。本地機通常也位於局域網內。

L 和 T 無法互相訪問,但 L 和 T 都能訪問 A。我們將 T 通過 ssh 連接到A,將 L 也通過 ssh 連接到A,A 用於轉發數據,這樣就能使用本地計算機 L 來訪問遠端設備 R。

2.1 目標機 T (sshc)

2.1.1 shell 中 T 連接 A

目標機 T 上的 sshc 連接代理機 A 上的 sshd:

ssh -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

這條命令的作用:
1. 建立一條 ssh 連接,T 上的 ssh 客戶端連接到 A 上的 ssh 服務器,A 的 IP 是 120.198.45.126,端口號是 10022,賬號是10022;
2. 如果有其他 ssh 客戶端連接到了 A 的 10022 端口上,則 A 會將這條連接轉發到 T,T 在內部建立新的連接,連接到本機 22 端口。

這條命令在 T 上執行。在 T 連接 A 這條命令里,T 是本地主機(local),A 是遠程主機(remote)。

解釋一下此命令各選項:

  • -T 不分配偽終端;
  • -f 使 ssh 進程在用戶輸入密碼之後轉入後台運行;
  • -N 不執行遠程指令,即遠程主機(代理機A)不需執行指令,只作端口轉發;
  • -g 允許遠程主機(代理機A)連接到本地轉發端口;
  • -R 將遠程主機(代理機A)指定端口上的連接轉發到本機端口;
  • frank@120.198.45.126
    表示使用遠程主機 120.198.45.126 上的用戶 frank 來連接遠程主機;
  • :10022:127.0.0.1:22
    表示本機迴環接口(127.0.0.1,也可使用本機其他網絡接口的地址,比如以太網 IP 或 WiFi IP)的 22 端口連接到遠程主機的 10022 接口,因遠程主機 10022 綁定的地址為空,所以遠程主機會監聽其所有網絡接口的 10022 端口。

在目標機 shell 中查看連接是否建立:

root@localhost:~# ps | grep ssh
22850 root      2492 S    ssh -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126
22894 root      3500 S    grep ssh

在目標機 shell 中關閉 ssh 連接:

kill -9 $(pidof ssh)

此時在目標機 T 和代理機 A 中查看 ssh 連接信息,兩端都可以看到 ssh 連接不存在了。

2.1.2 C 代碼中 T 連接 A 的處理

C 代碼中主要還是調用 2.1.1 節中的命令。但是由 C 代碼編譯生成的進程無法在命令行和用戶進行交互,因此要避免交互問題。

1. 避免首次連接時的 y/n(或yes/no) 詢問

如果是首次登錄代理機 A,本機(目標機 T)沒有 A 的信息,需用用戶手動輸入 y 之後才能繼續。打印如下:

root@localhost:~# ssh -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

Host '120.198.45.126' is not in the trusted hosts file.
(ssh-rsa fingerprint md5 86:09:0c:1b:fd:0b:02:8c:29:62:7f:ff:70:1b:64:f5)
Do you want to continue connecting? (y/n) 

如果 T 上有 A 的信息,可通過執行刪除操作:rm ~/.ssh/known_hosts 再進行上述測試。

如果是在 C 代碼中執行登錄命令,進程在後台自動運行,是無法和用戶進行交互的。為了避免交互動作,應該禁止 ssh 發出 y/n 的詢問。

如果 ssh 客戶端是 dropbear ssh,則添加 -y 參數,如下:

ssh -y -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

如果 ssh 客戶端是 openssh,則添加 -o StrictHostKeyChecking=no 選項,如下:

ssh -o "StrictHostKeyChecking no" -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

2. 避免輸入登錄密碼

避免由用戶手動輸入登錄密碼有如下方法:

1) 用 ssh-copy-id 把本地主機的公鑰複製到遠程主機的authorized_keys文件上,登錄不需要輸入密碼。
2) 用 expect 調用 shell 腳本,向 shell 腳本發送密碼。這種方式是模擬鍵盤輸入。
3) 如果是 openssh,則用 sshpass 向 ssh 命令行傳遞密碼。如果是 dropbear,則通過 DROPBEAR_PASSWORD 環境變量向 ssh 命令行傳遞密碼。

我們採用第 3 種方法。

假如代理機 A 上用戶 frank 密碼是 123456,則最終 C 代碼里應執行的指令如下:

# openssh
sshpass -p '123456' ssh -o "StrictHostKeyChecking no" -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

# dropbear
DROPBEAR_PASSWORD='123456' ssh -y -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

dropbear 無法接收 DROPBEAR_PASSWORD 變量傳遞密碼的處理方法:

dropbear 包含 ssh 客戶端和 ssh 服務器,體積小巧,常用於嵌入式設備。dropbear ssh 無法接收 sshpass 傳入的密碼信息。但 dropbear ssh 可以通過環境變量 DROPBEAR_PASSWORD 傳入密碼信息。openwrt 從某一版開始,通過打補丁的方式禁用了 DROPBEAR_PASSWORD 選項,我們可以找到對應的補丁,開啟 DROPBEAR_PASSWORD 選項,再重新編譯生成 dropbear。如下:

修改 dropbear patch 文件(如下路徑位於 openwrt 源碼根目錄):

vim package/network/services/dropbear/patches/120-openwrt_options.patch

將如下幾行刪除:

@@ -226,7 +226,7 @@ much traffic. */
  * note that it will be provided for all "hidden" client-interactive
  * style prompts - if you want something more sophisticated, use 
  * SSH_ASKPASS instead. Comment out this var to remove this functionality.*/
-#define DROPBEAR_PASSWORD_ENV "DROPBEAR_PASSWORD"
+/*#define DROPBEAR_PASSWORD_ENV "DROPBEAR_PASSWORD"*/
 
 /* Define this (as well as ENABLE_CLI_PASSWORD_AUTH) to allow the use of
  * a helper program for the ssh client. The helper program should be

重新編譯生成 dropbear,並替換設備里已安裝的 dropbear。

#define DEFAULT_SSH_AGENT_HOST      "120.198.45.126"
#define DEFAULT_SSH_AGENT_PORT      "10022"
#define DEFAULT_SSH_AGENT_USER      "ssha_debug"
#define DEFAULT_SSH_AGENT_PASSWD    "220011ssha"
int login_to_ssh_agent(const char *host, const char *port, const char *user, const char *passwd)
{
    // openssh client:
    // sshpass -p '123456' ssh -o "StrictHostKeyChecking no" -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

    // dropbear ssh clent:
    // DROPBEAR_PASSWORD='123456' ssh -y -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

    char cmd[256];
    snprintf(cmd, sizeof(cmd), "DROPBEAR_PASSWORD='%s' ssh -y -T -f -N -g -R :%s:127.0.0.1:22 %s@%s", 
             (passwd != NULL) ? passwd : DEFAULT_SSH_AGENT_PASSWD, 
             (port != NULL) ? port : DEFAULT_SSH_AGENT_PORT,
             (user != NULL) ? user : DEFAULT_SSH_AGENT_USER,
             (host != NULL) ? host : DEFAULT_SSH_AGENT_HOST);
    printf("login to ssh agent: \n%s\n", cmd);
    system(cmd);

    return 0;
}

2.2 代理機 A (sshd)

在 /etc/ssh/sshd_config 中添加如下幾行后重啟 ssh 服務:

GatewayPorts yes
UseDNS no
GSSAPIAuthentication no

目標機 T 發起連接后,在代理機 A 上查詢目標機 T 是否連接成功:

sudo netstat -anp | grep 10022

打印形如:

tcp        0      0 0.0.0.0:10022           0.0.0.0:*               LISTEN      8264/sshd: frank
tcp6       0      0 :::10022                :::*                    LISTEN      8264/sshd: frank

上述打印中,8264 就是和目標機 T 保持連接的 sshd 進程號,如需關閉當前連接重新建立一個新的連接,則先在代理機 A 上執行:

kill -9 8264

然後再執行 2.1 節的指令,就會建立一次新的代理連接。

為了安全,我們可以專門新建一個用戶,僅用於 ssh 端口轉發功能,不能在 shell 中使用此用戶登錄。如下創建一個 ssha_debug 的用戶,無 shell 登錄權限。然後為此用戶創建密碼。注意系統中 nologin 文件的位置,不同系統可能路徑不同。

sudo useradd ssha_debug -M -s /usr/sbin/nologin
sudo passwd ssha_debug

2.3 本地機 L (sshc)

2.3.1 本地機 L 登錄目標機 T

有三種方式:

1. 在本地機 L 上通過 ssh 登錄代理機 A,在 A 的 shell 中再登錄目標機 T

代理服務器的公網 ip 是 120.198.45.126,內網 ip 是 192.168.1.102。

1) 先使用 ssh(SecureCRT 或 OpenSSH 命令行) 登錄上代理服務器的 shell。如果調試機在內網,既可登錄代理機的外網 ip,也可登錄其內網 ip。

2) 在代理機的 shell 中執行如下命令登錄遠程設備:

ssh -p 10022 root@127.0.0.1 -vvv

注意,此命令中用戶 root 及其密碼是遠程設備上的賬戶。

如果提示 Host key 認證失敗之類的信息,請按提示執行如下命令:

ssh-keygen -f "/home/frank/.ssh/known_hosts" -R [127.0.0.1]:10022

也可直接刪除當前用戶目錄下的 .ssh/known_hosts 文件。
然後重新執行登錄設備操作。

建議優先使用此方法。

2. 在本地機 L 上使用 ssh 命令登錄目標機 T

Win 10 系統默認安裝有 OpenSSH 客戶端。可以在調試機 Windows 命令行中執行:

ssh -p 10022 root@120.198.45.126 -vvv

對於本地計算機來說,待調試的設備 ip 地址不可見。本機登錄到代理機 120.198.45.126 的轉發端口 10022,通過代理機轉發功能,本地機能成功登錄到遠程設備上。注意,此命令中用戶 root 及其密碼是設備上的賬戶,不是 SSH 代理服務器上的賬戶。

如果出現認證失敗之類的信息。可刪除 C:/Users/當前用戶/.ssh/known_hosts 文件,然後再試。

3. 在本地機 L 上使用 SecureCRT 工具登錄目標機 T

也可以直接使用 SecureCRT 軟件,設置好代理機的 ip(120.198.45.126) 和端口號(10022),填上設備的登錄用戶和登錄密碼。

不建議使用此方法。因為連接過程太長或連接失敗的話,無法看到錯誤提示信息。

2.3.2 查看代理機 A 打印信息

在 L 執行登錄 T 之前查看打印信息:

frank@SERVER:~$ sudo netstat -anp  | grep 10022
tcp        0      0 0.0.0.0:10022           0.0.0.0:*               LISTEN      106438/sshd: frank
tcp6       0      0 :::10022                :::*                    LISTEN      106438/sshd: frank

在 L 執行登錄 T 之後查看打印信息:

frank@SERVER:~$ sudo netstat -anp  | grep 10022
tcp        0      0 0.0.0.0:10022           0.0.0.0:*               LISTEN      106438/sshd: frank
tcp        0      0 192.168.1.102:10022     120.229.163.51:27027    ESTABLISHED 106438/sshd: frank
tcp6       0      0 :::10022                :::*                    LISTEN      106438/sshd: frank

可以看到,上述第二行是 L 執行登錄命令后新出現的打印信息。表示新建立了一條 L 到 A 的 ssh 連接。

L 端的外網地址 120.229.163.51:27027 連接到 A 上的 192.168.1.102:10022,L 通常位於局域網內、具有一個內網地址,120.229.163.51 可能是 L 連接的路由器的公網 IP。

這條連接建立后,A 將這條連接轉發到 R。

2.3.3 查看目標機 T 打印信息

在 L 執行登錄 T 之前查看打印信息:

root@localhost:~# netstat -anp | grep 22
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      917/sshd
tcp        0      0 192.168.202.140:47989   120.198.45.126:22       ESTABLISHED 9452/ssh
tcp        0      0 192.168.202.140:22      192.168.202.100:64737   ESTABLISHED 2041/sshd
tcp        0      0 :::22                   :::*                    LISTEN      917/sshd

在 L 執行登錄 T 之後查看打印信息:

root@localhost:~# netstat -anp | grep 22
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      917/sshd
tcp        0      0 192.168.202.140:47989   120.198.45.126:22       ESTABLISHED 9452/ssh
tcp        0      0 192.168.202.140:51732   192.168.202.140:22      ESTABLISHED 9452/ssh
tcp        0      0 192.168.202.140:22      192.168.202.140:51732   ESTABLISHED 9579/sshd
tcp        0      0 :::22                   :::*                    LISTEN      917/sshd

可以看到,上述第 3 行和第 4 行是登錄之後新增加的打印信息。

第 2 行,表示 T 上的 ssh 客戶端連接到了 A 上的 ssh 服務端,進程號是 9452。第 3 行,表示進程 9452 收到了 A 轉發來的 ssh 連接后,在本機內部建立新的 ssh 連接,使用 51732 端口號作為 ssh 客戶端,連接到本機 22 端口,22 端口是 sshd 端口。第 4 行,表示本機新啟動一個 sshd 進程,來接收 sshc 的連接。

這樣,L 到 T 的 ssh 通路徹底打通了。A 將來自 L 的連接轉發到 R,R 在內部啟動了 sshd 來處理來自 L 的請求,通過 A 的代理作用,實現了 L 上的 sshc 和 T 上的 sshd 的交互。

3. 典型使用場景步驟總結

上文已涵蓋詳細使用方法,但篇幅太長。此處簡單總結使用步驟如下:

3.1 在代理機 A 上執行

使用 SecureCRT 登錄代理機 A。代理機外網 ip 120.198.45.126,內網 ip 192.168.1.102,端口 22。如果本地機與代理機在同一個局域網裡,使用代理機的內網 ip 登錄即可。

在代理機 shell 中查看是否有未關閉的 ssh 隧道:

sudo netstat -anp | grep 10022

若打印形如:

tcp        0      0 0.0.0.0:10022           0.0.0.0:*               LISTEN      8264/sshd: frank
tcp6       0      0 :::10022                :::*                    LISTEN      8264/sshd: frank

則表示有未關閉的 ssh 隧道連接。執行如下命令可關閉連接。

kill -9 8264

3.2 在目標機 T 上執行

使用遠程應用程序接口或者在遠程設備 T 上做一些特殊操作,觸發 T 執行如下兩條指令之一:

# openssh
sshpass -p '123456' ssh -y -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

# dropbear
DROPBEAR_PASSWORD='123456' ssh -y -T -f -N -g -R :10022:127.0.0.1:22 frank@120.198.45.126

3.3 在本地機 L 上執行

在本地機 L 上執行如下指令,登錄遠程目標機 T:

ssh -vvv -p 10022 root@120.198.45.126

另外一種變通的方式是,在本地機先通過 ssh 登錄上代理機 A 的 shell。然後在 A 的 shell 中執行如下指令:

ssh -vvv -p 10022 root@127.0.0.1

4. 注意事項

1. 確保代理機 A 所在的網絡防火牆不屏蔽 10022 端口
2. 確保代理機 A 上 /etc/ssh/sshd_config 配置文件設置正確
3. 關閉 ssh 隧道既可在代理機 A 上進行(關閉相應的 sshd 進程),也可在目標機 T 上進行(關閉相應的 ssh 進程)
4. 每次只能訪問一台目標機。如果想同時訪問多台,可以代理機上設置多個轉發端口,每條連接使用一個端口進行轉發
5. 為保證安全,打開 ssh 隧道時盡量使用無登錄權限的用戶,並且此用戶的密碼建議經常更新

5. 參考資料

[1] 阮一峰,
[2]
[3]

6. 修改記錄

2019-11-20 V1.0 初稿

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

USB CONNECTOR掌控什麼技術要點? 帶您認識其相關發展及效能

※評比前十大台北網頁設計台北網站設計公司知名案例作品心得分享

※智慧手機時代的來臨,RWD網頁設計已成為網頁設計推薦首選

台灣海運大陸貨務運送流程

兩岸物流進出口一站式服務

分類
發燒車訊

數組與鏈表

前言

數組和鏈表是兩種數據結構,數組非常簡單易用但是它有兩個非常大的缺點,一個是數組一旦創建無法擴展,另一個則是數組的查找和刪除的速度很慢.

鏈表改善了一些數組的缺點,但是同樣的鏈表自身也存在一些自己的缺點.

本篇博客將為大家介紹一下這數組和鏈表特點及各自的優缺點.

閱讀前的準備工作

,一種粗略的評價計算機算法效率的方法.後面的內容會用到表示效率的方法.

1. 數組

我們按數組中的數組是否排序對數組進行劃分,將數組分為無序數組和有序數組.無序數組中的數組是無序的,而有序數組中的數據則是升序或者降序排序的.

1.1 無序數組

因為無序數組中的數據是無序的,往數組中添加數據時不用進行比較和移動數據,所以往無序數組裡面添加數據很快.無論是添加第一個數據還是第一萬個數據所需的時間是相同的,效率為O(1).

至於查找和刪除速度就沒有那麼快了,以數組中有一萬個數據項為例,最少需要比較1次,最多則需要比較一萬次,平均下來需要比較5000次,即N/2次比較,N代表數據量,大O表示法中常數可以忽略,所以效率為O(N).

結論:

  1. 插入很快,因為總是將數據插入到數組的空餘位置.
  2. 查找和刪除很慢,假設數組的長度為N,那麼平均的查找/刪除的比較次數為N/2,並且還需要移動數據.

1.2 有序數組

無序數組中存放的數據是無序的,有序數組裡面存放的數據則是有序的(有可能是升序有可能是降序).

因為有序數組中的數據是按升序/降序排列的,所以插入的時候需要進行排序並且移動數據項,所有有序數組的插入速度比無序數組慢. 效率為O(N).

刪除速度和無序數組一樣慢 效率為O(N).

有序數組的查找速度要比無序數組快,這是因為使用了一個叫做二分查找的算法.

二分查找: 二分查找也稱折半查找(Binary Search),它是一種效率較高的查找方法。但是,折半查找要求線性表必須採用順序存儲結構,而且表中元素按關鍵字有序排列.

有一個關於二分查找的形象類比 -> 猜數遊戲

假設要在0-100之間猜一個數,那麼你第一個要猜的数字就是100的一半50的時候,你的朋友會告訴你這個数字比要猜的数字是大還是小,如果比数字大,你接下來要猜的数字就是50的一半25,你的朋友說比這個数字要大,那麼你下面要猜的数字就是25-50中間的那個數37,以此類推…

使用二分查找可極大的提高查找的效率,假設一個有序數組有十億個數據,那麼查找到所需的数字,最多只需比較30次.

有序數組使用二分查找的效率為O(logN).有序數組也可以通過二分查找來新增和刪除數據以提高效率,但是依然需要在新增/刪除后移動數據項,所以效率依然會有影響.

總結:

  1. 有序數組的查找速度比無序數組高,效率為O(logN)
  2. 有序數組的刪除和新增速度很慢,效率為O(N)

1.3 數組總結

數組雖然簡單易用,但是數組有兩個致命的缺點:

  1. 數組存儲的數量有限,創建的過大浪費資源,創建的過小溢出
  2. 數組的效率比其他數據結構低
  • 無序數組插入效率為O(1)時間,但是查找花費O(N)時間
  • 有序數組查找花費O(logN)時間,插入花費O(N)時間
  • 刪除需要移動平均半數的數據項,所以刪除都是O(N)的時間

2. 鏈表

數組一經創建大小就固定住了,無法修改,鏈表在這方面做出了改善,只要內存夠用就可以無限制的擴大.

鏈表是繼數組之後應用最廣泛的數據結構.

2.1 鏈表的特點

鏈表為什麼叫鏈表呢? 因為它保存數據的方式就像一條鎖鏈

鏈表保存數據的方式很像上面的這一條鎖鏈,每一塊鎖鏈就是一個鏈節點,鏈節點保存着自己的數據同時通過自己的next()方法指向下一個鏈節點. 鏈表通過鏈節點不斷地調用next()方法就可以遍歷鏈表中的所有數據.

在鏈表中,每個數據項都被包含在”鏈節點”(link)中,一個鏈結點是某個類的對象,這個類可以叫做Link.因為一個鏈表中有許多類似的鏈結點,所以有必要用一個不同於鏈表的類來表達鏈結點.

每個Link對象中都包含一個對下一個鏈結點引用的字段(通常叫做next).

鏈表本身的對象中有一個字段指向對第一個鏈結點的引用.

數據與鏈表查找數據的區別: 在數組中查找數據就像在一個大倉庫裏面一樣,一號房間沒有,我們去二號房間,二號房間沒有我們去三號房間,以此類推.. 按照地址找完所有房間就可以了.

而在鏈表中查找數據就像單線彙報的地下工作者,你是孤狼你想要彙報點情報給你的頂級上司毒蜂,但是你必須先報告給你的接頭人豬剛鬣,豬剛鬣在報告給它的單線接頭人土行孫,最後由土行孫報告給毒蜂.只能一個找一個,這樣最終完成任務.

2.2 Java代碼

鏈節點類:


/**
 * @author liuboren
 * @Title: 鏈節點
 * @Description:
 * @date 2019/11/20 19:30
 */
public class Link {
    //  保存的數據
    public int data;

    // 指向的下一個鏈節點
    public Link nextLink;

    public Link(int data) {
        this.data = data;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public Link getNextLink() {
        return nextLink;
    }

    public void setNextLink(Link nextLink) {
        this.nextLink = nextLink;
    }
}

鏈表類


/**
 * @author liuboren
 * @Title: 鏈表類
 * @Description:
 * @date 2019/11/20 19:31
 */
public class LinkList {
    private Link first;

    public LinkList() {
        first = null;
    }

    // 新增鏈節點方法
    public void insertFirst(int data) {
        Link link = new Link(data);
        link.setNextLink(first);
        first = link;
    }
}

在新增節點的時候,新增的link的next方法指向原來的first節點,並將鏈表類的first指向新增的節點.

2.4 其他鏈表

剛剛介紹的鏈表是單向鏈表,只能從后往前遍歷,其他的鏈表還有雙端鏈表、雙向鏈表、有序鏈表.

再簡單介紹一下雙端鏈表吧.

雙端鏈表就是在單向鏈表的基礎上,新增一個成員變量指向鏈表的最後一個對象.

雙端鏈表代碼:

/**
 * @author liuboren
 * @Title: 鏈表類
 * @Description:
 * @date 2019/11/20 19:31
 */
public class LinkList {
    private Link first;
    private Link last;

    public LinkList() {
        first = null;
    }

    public boolean isEmpty() {
        return first == null;
    }

    // 新增鏈節點方法
    public void insertFirst(int data) {
        Link newLink = new Link(data);
        newLink.setNextLink(first);
        if (isEmpty()) {
            last = newLink;
        }
        first = newLink;

    }
}

雙向鏈表則是可以從first和last兩個方向進行遍歷,有序鏈表的數據都是按照關鍵字的順序排列的,本文不再展開了.

2.5 鏈表的效率

鏈表的效率:

  • 表頭插入和刪除速度都很快,花費O(1)的時間.
  • 平均起來,查找&刪除&插入在制定鏈節點後面都需要搜索一半的鏈節點需要O(N)次比較,雖然數組也需要O(N)次比較,但是鏈表讓然要快一些,因為不需要移動數據(只需要改變他們的引用)

3. 總結

鏈表解決了數組大小不能擴展的問題,但是鏈表自身依然存在一些問題(在鏈表的鏈節點後面查找&刪除&插入的效率不高),那麼有沒有一種數據結構即擁有二者的優點又改善了二者的缺點呢,答案是肯定的,下篇博客將為您介紹這種優秀的數據結構,敬請期待.

本站聲明:網站內容來源於博客園,如有侵權,請聯繫我們,我們將及時處理

【其他文章推薦】

※想知道網站建置網站改版該如何進行嗎?將由專業工程師為您規劃客製化網頁設計後台網頁設計

※不管是台北網頁設計公司台中網頁設計公司,全省皆有專員為您服務

※Google地圖已可更新顯示潭子電動車充電站設置地點!!

※帶您來看台北網站建置台北網頁設計,各種案例分享

小三通物流營運型態?

※快速運回,大陸空運推薦?