Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

[Flash] Flash Socket & C++/Java Socket

  • Flash Socket & C++/Java Socket
  • Download: SocketComm.zip Java_C_Comm.zip

    根據Google Analytics資料顯示,我的部落格點閱率最高的文章竟然是[C/C++] Socket Connection ,為此我決定再增加Flash Socket的部份。

    這一篇是最簡單的範例,只是實做讓Flash Socket與C++/Java Socket互通,因為Flash Socket僅有Client的連線功能,Server的部份我們必須仰賴C++/C#/Perl/Java/PHP等語言來完成。預覽畫面如下(Flash Client Side):

    Server-Side (Server的部份則是直接沿用[C/C++/JAVA] Socket Communication Between JAVA and...這篇的程式碼)

    Waiting for Connection......
    Connected from 192.168.2.49/192.168.2.49:1899
    Hello! I'm Flash Client

    程式碼的部份其實很單純,唯一要講解的只有傳送的部份:

    private function sendData():void{
    var buff:ByteArray = new ByteArray();
    buff.writeMultiByte(input.text+"\n","unicode");
    socket.writeBytes(buff);
    socket.flush();
    output.appendText(input.text);
    input.text = "";
    }

    可以看到我們在傳送數據時用的是writeBytes而不是writeUTFBytes,這麼做的原因是要解決中文會亂碼的問題。傳送完之後記的要呼叫flush(),如此才能正常傳送出去。

    關於編碼的資料可以參考下面的網頁:

    http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/charset-codes.html

    Policy File的資訊請參考下面的網頁:

    http://www.adobe.com/devnet/flashplayer/articles/fplayer9_security_print.html

    有了上面的簡單概念之後,你可以將Flash的介面稍加修改,再配合之前的聊天程式的片段,就可以組合成聊天室了。

[C/C++/JAVA] Socket Communication Between JAVA and C/C++

  • Socket Communication Between JAVA and C/C++
  • Download: Java_C_Comm.zip

    最近需要讓多個不同的語言互相溝通傳輸,所以我採用的Socket做為通訊的基礎,在這一篇裡我們以Java Socket和C Socket為例,而Java與C的通訊概念跟這一篇[C/C++] Socket Connection是一樣的,只是要注意的是你所傳送的型態會不會有little/big endian的問題,以及各語言函式所判定的結束字元。

    對Java設計者而言,Java提供了ServerSocket和Socket這兩個類別,設計者只需要import java.net使用這兩個類別就可以完成Server-Client的設計。

    對C/C++設計者而言,如果不使用已經封裝好的Socket API,多半是使用Unix Socket的基礎來堆出一個Server-Client的程式,自然會比Java困難許多。

    這裡為了照顧兩個平台的使用者,我將C語言的Socket部份同時使用Unix Socket以及WinSocket來完成,並且以Java Socket的OOP概念將他們封裝成Server與Client類別。

    /*** Server類別定義如下:***/

    class Server{
    public:
    Server(const int port);
    ~Server();

    #ifdef _WIN32
    bool initWsa();
    #endif

    bool create();
    bool bind(const int port);
    bool listen();
    SOCKET accept();

    bool isValid() const;

    void close();
    private:
    int state;
    SOCKET socket;
    };

    多數人會將accept後的socket存放在Server的類別裡,這樣的定義很不好,因為Server類別裡不應該去實做send(), recv()這兩個輸出輸入的成員函式,因為Server最主要的功用就是監聽並建立連線。

    /*** Client 類別定義如下: ***/

    class Client{
    public:
    Client(){};
    Client(const char* ip, const int port);
    ~Client();

    #ifdef _WIN32
    bool initWsa();
    #endif

    bool create();
    bool connect(const char* ip, const int port);

    int send(const char* buf) const;
    int recv(char* buf);

    bool isValid() const;

    int operator = (SOCKET socket);
    int operator << (const char* buf) const;
    int operator >> (char* buf);

    void close();

    private:
    int state;
    SOCKET socket;
    };

    其中的operator = 的overload是為了給為Server socket做accept用的。

    兩個程式片段有些地方重複,為什麼不先自訂一個Socket類別,然後讓兩個類別都去繼承Socket?如同前面所提的,Server是不應該去實做send(), recv() ,所以扣掉這些,這兩個類別相同之處就更少了,我是覺得沒有必要讓他們都去繼承Socket類別。

    程式有不少地方仍保留C型態,且例外處理做的不完全,還請包含。

    說了這麼多都還沒提到這篇的重點,Java跟C通訊的關鍵,下面以C做為Server,Java做為Client互相傳送的程式碼。

    關於Winsocket的設計者而言,必須要小心處理WSA的問題,所以我將WSA清除的部份放在deconstructor裡,直到物件被釋放時才清除WSA,這樣做是為了方便Server端去關閉Client端連線,而不造成Server的WSA也被清掉。

    如果覺得光看解說難以懂,那你就下載原始碼慢慢看吧!

    /*** C Socket ***/

    client.send("Hello! I'm C++ Server.\n");
    client.recv(buf);

    /*** Java Socket ***/

    BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
    buf = in.readLine();
    PrintStream out = new PrintStream(socket.getOutputStream());
    out.print("Hello! I'm Java Client.\n");

    c socket的部份跟之前範例的使用方式是完全一樣的,只是在傳送的結尾我們要加上\n,因為在Java接收的那一端是以readLine()為基準,所以如果沒有跳行字元\n, Java那一端會繼續阻塞,直到對方連線中斷為止。當字串送達Java那一端之後,換行字元會被去掉,所以在列出console時還是要使用換行列出。

    所以簡單的Java與C的通訊該念就只有上面這麼一點,不管是什麼語言的互通,盡量以byte字元基準來傳送,比較不會送達到另一端語言接收後與原先不同的情形發生,但如果是比較複雜的編碼部份,有機會碰到我再補上來吧!

  • 編譯:
  • Linux 用戶:

    C語言部份我使用g++,Java部份我使用gcj,所以編譯之前請先裝這兩個編譯器。

    編譯方式如下:

    全部編譯:

    make -f makefile.gcc

    只編譯c++部份:

    make -f makefile.gcc cpp

    只編譯Java部份:

    make -f makefile.gcc java

    如果你還要使用的更細節的編譯部份,那你直接參考makefile.gcc的設定。

    Window 用戶(不保證能正常):

    C語言部份我使用mingw-g++,Java部份我使用mingw-gcj

    編譯方式如下:

    全部編譯:

    make -f makefile.mingw

    只編譯c++:

    make -f makefile.mingw cpp

    只編譯java:

    make -f makefile.mingw jav

    至於為什麼java的編譯方式是使用jav,而不是使用java,我也不知道mingw的make是怎麼了,我用java他總是給我說up to date,也就是一直不給我編譯。

    Java的部份其實我一直都不是很推薦使用gcj來編譯,但是這裡只是單純為了方便,且程式也很小,所以就將就一下。不然我比較推薦eclipse。

    為了要讓windows平台下能夠運作,花了不少時間在編譯設定上面,相關的套件可以參考這一篇[GCC] GCC for Windows (MinGW/DEV-C++)

  • 範例畫面:
  • Server : C++

    Client : Java

    /*** Server ***/

    /*** Client ***/

    當然上面是一個很簡單的範例,未來再繼續增加複雜的結構啦!

UTips. 51: gcj

  • gcj
  • Java的compiler除了可以使用eclipse,你可以使用gnu的gcj來編譯,下面是一個很簡單的程式碼:

    透過下面的指令來編譯:

    • gcj -c -g -O HelloJava.java
    • gcj --main=HelloJava -o HelloJava HelloJava.o

    雖然用gcj編譯出來的執行效率跟eclipse差不多,但是以開發的方便性來講,我還是比較推薦eclipse。

UTips, 50: eclipse

  • eclipse
  • 在Linux底下我比較推薦使用eclipse來做Java 的開發工具。

    • sudo apt-get install eclipse

    其實eclipse是跨平台的,在windows底下也可以使用eclipse。

[ANN] BackPropagation

  • BackPropagation
  • 在[ANN] Perceptron這一篇我們可以得知沒有隱藏層的Perceptron是無法解決XOR的問題,就算我們自行加了隱藏層也沒有對應的演算法去計算隱藏層的值,Paul Werbos於1974提出了BackPropagation Neural Network並解決隱藏層演算的問題。

    各參數意義如下:

    • X1,X2 :輸入層,兩個inputs
    • H1,H2 :隱藏層,兩個hidden nodes
    • Y:輸出層,一個output
    • thetaxh1,thetaxh2 :隱藏層的bias
    • thetahy:輸出層的bias

    而使用BackPropagation的網路時通常會搭配著以下兩種Transfer Function:

    • Sigmoid:
    • Hyperbolic Tangent:

    網路計算公式如下:

    如過算出的Y值沒又達到目標值,我們必須計算delta以及更新Weight跟Bias

    delta的計算公式如下:

    計算weight值


    計算Bias值

    更新所有的weight和bias

    重複上述的運算直到收斂到目標值為止,依據上述的公式我分別使用了C,Java,Perl來實做BackPropagation

    Download: BackPropagation.c BackPropagation.java BackPropagation.pl

    除了可以比較運行的速度之外,也可以探討精準度,速度方面當然是c語言佔上風,但是精準度卻沒有Java跟Perl,詳細的資料你可以參考下面的網頁。

    http://www.adahome.com/History/Steelman/steeltab.htm

    在學習速率方面筆者我並沒有讓他們給固定,我使用了下面這行程是碼:

    這裡我只是簡單的利用到二次曲線去變動學習速率,而變動依據則是按照目標差距值而定。只是這樣的修改方式並沒有什麼根據,比較好的動態學習速率應該依照DBD,EXDBD或者weight值得觀察來變動,這部份詳細訊息我們之後再來探討。


    關於誤差計算方式我則是使用RMSE

    當然你可以使用其他方式去計算誤差,RMSE在這個範例裡並不是那麼的重要。輸出畫面如下:

    以學習速率0.1為基準,在c語言版本下我們花了0.024秒,算了4000多個epoch之後得到我們的RMSE在0.1以內的解。結果可以說是相當不錯。當然還是有幾個問題需要探討。在多次測試下你可能會發現有時後會收斂不完全,這些問題筆者我會在之後逐一去講解。

Orange - data analysis tool

Installation pip install orange3 Run orange python -m Orange.canvas