2015年9月23日 星期三

linux下使用ping指令來快速知道網路是否連上Internet

最近再作NTP(網路同步時間)的功能,因此在使用者選擇好要同步的NTP Server之前,我必須先確認網路是可以連上Internet的

ping -q -c1 -W1 168.95.1.1

上面是關鍵的command,使用ping再加上它的一些參數,可以很快的知道網路是否有連上Internet。

這裡先說明一下ping參數的意義:
-q     => 不顯示任何傳送封包的資訊,只顯示最後的結果
-c1   => 在發送指定數目的包後停止,c1也就是只發一次的意思
-W1 => 等待回應的時間,W1就是只等待一秒


詳細的程式碼如下:
===================================================================

// NTP Server
#define NTP_SERVER_1 "tock.stdtime.gov.tw"      //response time is short.
#define NTP_SERVER_2 "tw.pool.ntp.org"
#define CH_TELECOM "168.95.1.1"                       //中華電信DNS

int ping_result(char *server)
{
        char cmd[64]={0};
        int ping_ret, status;

        sprintf(cmd, "ping -q -c1 -W1 %s 1>/dev/null 2>&1", server);
        status = system(cmd);
        if(-1 != status)
                ping_ret = WEXITSTATUS(status);

        if((status == 0) && (ping_ret == 0))    // If network can work on internet, these two value will be zero.
                return 1;
        else
                return 0;
}

void ping_ntp()
{
        int pingResult = ping_result(CH_TELECOM);    //ping CHT DNS first.
        if(pingResult == 1)
        {
                pingResult = ping_result(NTP_SERVER_1);      //second ping NTP Server.
        }

        if(pingResult == 0 )
        {
                printf("NETWORK_ERROR");
        }
        else
        {
                printf("RESPONSE_SUCCESS");
        }
}
=================================================================

這裡再說明一下,上面的ping_ntp的function當中,我會先去ping中華電信的DNS(168.95.1.1),這樣可以先知道是否有通Internet,第二步才去確認NTP SERVER是可以work的,若是連Internet都不通,也不必再花時間去ping NTP SERVER了~

2015年9月22日 星期二

opencv研究 關於CommandLineParser的用法

最近在看一些opencv的example source code,看到了CommandLineParser是以前沒有用過的class,因此瞭解了它的用法之後,把它記錄在這裡~

我這邊是拿opencv 3.0.0中的sample的image_alignment.cpp來當說明範例

首先要使用這fuction時都會在前頭先宣告一個"key",大概如下方所示:

============================================================
const std::string keys =
    "{@inputImage       | ../data/fruits.jpg | input image filename }"
    "{@templateImage |                            | template image filename (optional)}"
    "{@inputWarp        |                           | input warp (matrix) filename (optional)}"
    "{n numOfIter        | 50                       | ECC's iterations }"
    "{e epsilon              | 0.0001                | ECC's convergence epsilon }"
    "{o outputWarp      | outWarp.ecc       | output warp (matrix) filename }"
    "{m motionType    | affine                   | type of motion (translation, euclidean, affine, homography) }"
    "{v verbose             | 0                          | display initial and final images }"
    "{w warpedImfile   | warpedECC.png  | warped input image }"
;
===================================================================

接著會看到在main裡頭會先作CommandLineParser的宣告,宣告完之後會跟著一些parser資訊的程式碼:

int main (const int argc, const char * argv[])
{
    CommandLineParser parser(argc, argv, keys);

    string imgFile = parser.get<string>(0);
    string tempImgFile = parser.get<string>(1);
    string inWarpFile = parser.get<string>(2);

    int number_of_iterations = parser.get<int>("n");
    double termination_eps = parser.get<double>("e");
    string warpType = parser.get<string>("m");
    int verbose = parser.get<int>("v");
    string finalWarp = parser.get<string>("o");
    string warpedImFile = parser.get<string>("w");
       .
       .
       .
}
======================================================================

其實parser宣告完成之後,就可以用來取得key裡面的一些資訊,我們一行行來說明:

string imgFile = parser.get<string>(0); ===> 搭配key的寫法,這可以取到argv[1]的值,也就是執行檔後面第一個參數的值。

string tempImgFile = parser.get<string>(1); ===> 同理,可取到argv[2]的值。
string inWarpFile = parser.get<string>(2);  ===> 同理,可取到argv[3]的值。(若沒輸入,取到值為空)

 int number_of_iterations = parser.get<int>("n"); ==>可取出key的內容當中一開始有"n"的那一行並取到第一個符號("|")後面的值,在這邊我們可以取到"50"。

 double termination_eps = parser.get<double>("e"); ==>與上面同理,這範例當中我們可以取到"0.0001"
 string warpType = parser.get<string>("m"); ==>與上面同理,這範例當中我們可以取到"affine"
 int verbose = parser.get<int>("v"); ==>與上面同理,這範例當中我們可以取到"affine"
 string finalWarp = parser.get<string>("o"); ==>與上面同理,這範例當中我們可以取到"0"
 string warpedImFile = parser.get<string>("w"); ==>同理,我們可以取到"warpedECC.png"

而每一行的第二個"|"符號後面的資訊,類似說明的效果。


parser.printParams(); ==>可以把所有key的內容印出來


下圖是把這些parse出來的值印出來的結果:




2015年8月21日 星期五

在linux環境下,Windows與Linux檔案格式的差異性分析

    大家應該都有遇過這樣的問題,如果拿一個在windows環境下編輯的文字檔,拿到linux下作vim,在結尾的部分會出現^M的符號,其實這是因為windows以及linux換行符號不同所造成的。

首先介紹最常使用的三種作業系統,他們的換行符號如下所示:
       
      Linux:     "\n"
Windows:     "\r\n"
      MAC:     "\r"    (MAC的部分可能尚需查證,作者是網路上找的資料,並未實際求證)


以下我們作個實驗,首先在Windows系統下編輯一個檔案名為windows.txt,而內容則輸入"aaa"接著換行再輸入"bbb",編輯完成後把此檔案傳到Ubuntu為作業系統的電腦底下。

另外在Ubuntu為環境的電腦下,用vim編輯一個內容相同的檔案,名為linux.txt。



Linux底下有個好用的指令叫作"od",他可以用來查閱非文字檔內容,在這裡我們用這個指令查閱檔案內容,並以ASCII方式印出內容。

指令用法為 "od -c 檔名"


下圖是用上面的命令對windows.txt與linux.txt印出的結果:











我們可以明顯的看到 第一個印出來的windows.txt內容,換行符號確實是"\r\n",而linux.txt的換行符號卻是"\n",另外linux下編輯的檔案,也自動在第二行"bbb"的最後面多加了一個"\n"(作者vim這個檔案時,當輸入完"bbb"並沒有再按Enter鍵)

因此windows編輯的檔案要拿到linux下處理的時候,必須要特別小心注意!!


=========================================================
另外下面是一個可以把檔案中的內容,一行一行印出的shell script名子叫Danny_test.sh:

FILE_NAME="./windows.txt"

echo "" >> $FILE_NAME

if [ -f "$FILE_NAME" ]; then
        exec < $FILE_NAME
 
        while read line
        do
                #line=`echo $line| sed 's/\r//g'`
                line=`echo $line`
                echo $line
        done
fi

執行結果如下圖:









結果發現,只印出第一行aaa,bbb卻沒印,這裡有兩個原因:

1. 因為windows的換行符號\r\n跟linux的\n不同所造成
2. 因為windows下編輯的檔案結尾若沒有換行是不會加上\n的,linux下會自行加\n


接著分別解決方法
1. 使用sed 來將\r替換掉即可===>  line=`echo $line| sed 's/\r//g'`
2. echo "" >> windows.txt ,這樣作檔案的後面就會加上\n了


因此Danny_test.sh可以這樣寫:

FILE_NAME="./windows.txt"

echo "" >> $FILE_NAME

if [ -f "$FILE_NAME" ]; then
        exec < $FILE_NAME
 
        while read line
        do
                line=`echo $line| sed 's/\r//g'`
                echo $line
        done
fi

執行結果:


2015年8月5日 星期三

申請網卡MAC Address流程

每張網卡當出產時都需要有一組自己獨有的MAC Address,因此這樣的MAC位址是必須要申請的,還需要付一點費用。

負責管理MAC位址的是IEEE這個組織,要申請時請上他們的網站。
入口網如下面連結:
http://standards.ieee.org/develop/regauth/oui/index.html

我這邊來說明一下向IEEE申請時有以下幾種方案,如下圖所示,因為網頁都是英文版的因此我再詳細的對這三種方案說明一下:








1. MA-L(Mac Address Large)
申請這種方案感覺是最划算的,因為這方案可以使用的MAC Address數量最多,因為總共12位16進制的MAC,廠商ID會佔前六碼,其他六位數都由廠商自行使用,也就是說總共有16^6=16777216這麼多組可以使用,也就是約有1677萬個MAC Address可以使用。
接著我們來看一下申請所需的費用,如下圖所示:









第一欄位是申請MA-L方案所需的費用,大概是US.2575元。

第二欄位比較貴,因為第二欄位的種類是Private的,我的解讀是申請此種類的是無法在IEEE的網站上搜尋到公司對應的Address位址,因此還要額外再加上2980的費用。

第三欄位則是比第一欄貴了一點,它也是會對你的公司以及對應的MAC作隱藏的動作讓別人無法搜尋到,不過隱藏的時間只有一年。




2.MA-L(Mac Address Middle)
這個是IEEE新的方案,以往只有Large以及Small可以選,這個方案擁有的Mac Address數量大概有16^5=100萬個。費用表如下圖所示:










3.MA-S(Mac Address Small)
最後這個方案,針對的對象應該是比較偏向個人,因為它分配到的MAC總數量只有16^3=4096個,費用也只需要US.645元,感覺不太划算。










上面介紹完各種方案之後就看自己怎麼選擇囉!



各方案的申請網址(點選左邊欄位的Application)
MA-L       https://standards.ieee.org/regauth/application/mal/show


查詢公司申請的MAC(也可以透過點選左邊欄位 Public Listing到下面連結)

2015年7月29日 星期三

IE瀏覽器當VLC播放rtsp串流時切換頁面無回應的解決方法(onclick、onunload、herf優先順序)

今天在弄網頁的部分,網頁的內容有用到內嵌VLC,使用的Browser是IE

遇到一個很頭痛的問題是,當要從播放RTSP的VLC頁面中切換到別的頁面時,總是會造成IE Hang住,然後IE無回應 這時候IE只能強制關閉,然後重開。

猜想是因為離開頁面時,應該要呼叫VLC的Stop function先停止,再進行切換的動作。

先說明我網頁的架構如下圖所示,整個網頁有作分割式窗,上面小視窗的連結(herf)點擊之後,會在下面的main_Frame切換到超連結的頁面。另外每個Herf的區塊都有作自己要處理的onclick() function。
















後來我查了一些資料得知,當頁面要離開到別的頁面時,javascript的部分會去作windows.onunload() 函式,因此我就把這個VLC的Stop function加入在這個onunload()當中。但後來發現情況並沒有改善。

在查詢了一些資料後,又有一個重大發現,原來onclick()、onunload()、herf這三個東西是有一個優先順序的,動作的先後順序為 onclick() => onunload() => herf

因此我把VLC的Stop function加入到架構圖中的上面三個的onclick事件要做的function當中,就解決了這個IE瀏覽器當VLC播放rtsp串流時切換頁面無回應的問題。

下面程式碼為javascript,附上javascript在mainFrame以及topFrame分別要呼叫VLC stop的程式碼:

=============== mainFrame 的 javascript部分 ==============
function getVLC(name)  
{  
        if (window.document[name])    
        {  
                return window.document[name];  
        }  
        if (navigator.appName.indexOf("Microsoft Internet")==-1)  
        {  
                if (document.embeds && document.embeds[name])  
                        return document.embeds[name];    
        }  
        else  
        {  
                return document.getElementById(name);  
        }  
}  

getVLC("vlc").playlist.stop();





=============== topFrame 的 javascript部分 ==============
function getVLC(name)  
{  
        if (self.parent.frames["mainFrame"].document[name])    
        {  
                return self.parent.frames["mainFrame"].document[name];  
        }  
        if (navigator.appName.indexOf("Microsoft Internet")==-1)  
        {  
                if (self.parent.frames["mainFrame"].embeds && self.parent.frames["mainFrame"].document.embeds[name])  
                        return self.parent.frames["mainFrame"].document.embeds[name];    
        }  
        else  
        {  
                return self.parent.frames["mainFrame"].document.getElementById(name);  
        }  
}  

getVLC("vlc").playlist.stop();




2015年7月21日 星期二

cross compiler openssl遇到的 target already defined - linux-elf (offending arg: CC=arm-linux-gcc) 問題~

今天在研究openssl,準備針對抓下來的opensource作cross compiler。

openssl的下載點(OPENSSL),我抓的版本為openssl-1.0.2a。

首先解開壓縮包之後,先作configure的動作,指令如下:

#./config CC=arm-linux-gcc

但不知道為什麼,一直出現下面的訊息,導致config無法完成
==>  target already defined - linux-elf (offending arg: CC=arm-linux-gcc)



後來把指令改了一下,可以運作的指令如下:

#CC=arm-linux-gcc ./config no-asm shared



成功編譯完成的openssl執行檔會在 apps資料夾中

2015年7月1日 星期三

可變參數的function實作

由於最近寫的程式常常需要用到strcat ,而且一次要把好多個值strcat在一起

因此對可變參數的函式作了小小的研究,並寫成function以便日後使用


================== 正題開始 =================

在C/C++中,有所謂的variant argument(變動引數)。也就是可以讓函數
使用數量不固定的引數。printf()就是這類的函數。

定義一個函數的prototype(原型)時,若是將參數列以"..."代入,就表示這個函數即將
使用variant argument。如:

danny_func(char *result,  ...)

這樣子便可讓編繹器不檢驗傳入這種函數裡的引數型態和數量,編出來的程式碼在呼叫端
就能夠盡可能地把各式各樣引數傳入。


那麼,在如此的程式裡,要怎麼存取variant argument呢?因為缺少引數變數,所以我們
不可能像一般程式一樣直接存取它們,而是要改用stdarg.h裡面所提供的三個巨集與一個
型別,分別是:

va_list: 宣告一個指標,讓它指向引數串列。
va_start: 初始化這個指標,讓它真正指向正確的引數串列開頭。
va_arg: 來取得va_list中的資料。
va_end: 清除這個指標,把它設為NULL。範例如下:

因此打算實作一個 danny_strcat(char *result,  ...) 這樣子的function。

首先還是必須先使用到上面介紹的 linux當中的這些函式。




實作範例如下:
================= danny_strcat.c ====================
#include <stdio.h>
#include <string.h>
#include <stdarg.h>

void danny_strcat(char *result,  ...)
{
     va_list ap;
     char *p;
     va_start(ap, result);
     p = va_arg(ap, char *);

     while (p != NULL) {
      strcat(result, p);
      p = va_arg(ap, char*);
     }
     va_end(ap);
}

int main(void)

{
     char tmp[512]={0};
     char tmp2[32]="strcat";
     danny_strcat(tmp, "hello-", "world-", "danny-", tmp2, NULL);
     printf("In main tmp=%s\n",tmp);
     return 0;
}


輸出結果:






*目前的作法- 當呼叫這個可變參數的函式時,使用者必須在參數的最後面加上NULL,來告知它結束的點。