Thursday, May 8, 2014

Apache MPM Worker + mod_fastcgi + PHP-FPM

Apache MPM Worker + mod_fastcgi + PHP-FPM

Quick Notes:
[] There are two kinds of Apache MPM (Multi-Processing Modules):
- prefork
- worker (threaded MPM)

[] Apache MPM:
- MPM prefork + mod_php
- MPM worker (threaded MPM) + mod_fastcgi
- MPM worker (threaded MPM) + mod_fcgid

Note: if you want to use either mod_fastcgi or mod_fcgid, be aware of that each process has its own APC opcode cache, which in turn wastes memory resource, unless you use PHP-FPM to share APC cache between processes.

[] 由於 php-fpm 是自帶的 FastCGI Process Manager , 所以和原本的 php fastcgi 有所不同 , php-fpm 若要搭配 Apache 只能以 mod_fastcgi 來運作 , 原本 Apache 有開發 mod_fcgid , 但 mod_fcgid 本身算是個 FastCGI Process Manager , 只能執行本地端 FastCGI , 而 php-fpm 可以用 Unix Socket 或 TCP 模式讓任何具備執行外部 FastCGI 程序的 WebServer 連接 , 因此 lighttpd 或 Ngix 等都可以 , 唯獨世上次爛的 Apache 要外掛 mod_fastcgi , 最爛的當然是 IIS 了 , 哈

[] PHP-FPM not only supports TCP/IP connections (ex: 127.0.0.1:9000) but also the socket based connections (ex: /tmp/php-fpm.sock).

The advantage of running PHP-FPM on socket connections instead of TCP/IP is that the socket connections are much more faster than TCP/IP connections (around 10-15%) because it saves the passing the data over the different layers of TCP/IP stack.
Therefore, it is recommended to run the PHP-FPM on socket connections over TCP/IP when you are using the same server for Apache and PHP-FPM. If you are using the different servers for Apache and PHP-FPM then the socket connections for PHP-FPM will not work.

[] the topic of sharing APC opcode cache between processes.

[] Apache 改為 MPM Worker 模式運作 (instead of MPM prefork)

甚麼是 worker 模式 ? 簡單來說就是 Apache 會搭配多行程 + 多執行緒的方式運作 , 每個行程會有多個執行續同時服務客戶端連線 , 記憶體及效能都較好 , 由於 php-fpm 或 php fastcgi 都已經是獨立於 Apache 行程了 , 所以 Apache 若再跑 prefork 模式就浪費了 , 因此可以切換為 worker 模式 。

[] Use mod_fastcgi's FastCgiExternalServer to point to PHP-FPM, no more wrapper script please!!

[] Most of apache config examples are outdated or wrong, or copy from other wrong articles.

[] PHP-FPM is a daemon and mod_fcgid's official site (http://httpd.apache.org/mod_fcgid/mod/mod_fcgid.html) is not talking about PHP-FPM, it is talking about php patched with fastcgi library http://www.fastcgi.com/drupal/node/5?q=node/10.

[] PHP-FPM is native in PHP since 5.3.3, so the mod_fcgid is not the choice for PHP user at the mean time, unless it provide Directive similiar to mod_fastcgi's FastCgiExternalServer.

[] Why shouldn't I use Apache2 with a threaded MPM in a production environment?
PHP is glue. It is the glue used to build cool web applications by sticking dozens of 3rd-party libraries together and making it all appear as one coherent entity through an intuitive and easy to learn language interface. The flexibility and power of PHP relies on the stability and robustness of the underlying platform. It needs a working OS, a working web server and working 3rd-party libraries to glue together. When any of these stop working PHP needs ways to identify the problems and fix them quickly. When you make the underlying framework more complex by not having completely separate execution threads, completely separate memory segments and a strong sandbox for each request to play in, further weaknesses are introduced into PHP's system.

If you want to use a threaded MPM, look at a FastCGI configuration where PHP is running in its own memory space.

http://php.net/manual/en/faq.installation.php

System Specifications
- FreeBSD 8.2-STABLE-201105
- apache-worker-2.2.19
- php5-5.3.6_1
- php5-extensions-1.5
- mysql-server-5.5.13
- ap22-mod_fastcgi-2.4.6_1
- pecl-APC-3.1.9_1
- memcached-1.4.5_2
- pecl-memcached-1.0.2

Install Apache
# cd /usr/ports/www/apache22-worker-mpm ; make install

Install PHP5
# cd /usr/ports/lang/php5 ; make install
or
# cd /usr/ports/lang/php52 ; make install

FPM=on "Build FPM version (experimental)"
MULTIBYTE=on "Enable zend multibyte support"
SUHOSIN=on "Enable Suhosin protection system"
MAILHEAD=on "Enable mail header patch"
LINKTHR=on "Link thread lib (for threaded extensions)"

/usr/ports/lang/php52 # make showconfig
===> The following configuration options are available for php52-5.2.17_2:
CLI=on "Build CLI version"
CGI=on "Build CGI version"
APACHE=off "Build Apache module"
DEBUG=off "Enable debug"
SUHOSIN=on "Enable Suhosin protection system (not for jails)"
MULTIBYTE=on "Enable zend multibyte support"
IPV6=off "Enable ipv6 support"
MAILHEAD=on "Enable mail header patch"
REDIRECT=off "Enable force-cgi-redirect support (CGI only)"
DISCARD=off "Enable discard-path support (CGI only)"
FASTCGI=on "Enable fastcgi support (CGI only)"
FPM=on "Enable fastcgi process manager (CGI only)"
PATHINFO=on "Enable path-info-check support (CGI only)"
LINKTHR=on "Link thread lib (for threaded extensions)"
===> Use 'make config' to modify these settings

Copy php.ini file
// For PHP5.3
# cp /usr/local/etc/php.ini-production /usr/local/etc/php.ini

// For PHP5.2
# cp /usr/local/etc/php.ini-recommended /usr/local/etc/php.ini

Install PHP Extensions
# cd /usr/ports/lang/php52-extensions ; make install

/usr/ports/lang/php52-extensions # make showconfig
===> The following configuration options are available for php52-extensions-1.3_1:
BCMATH=off "bc style precision math functions"
BZ2=off "bzip2 library support"
CALENDAR=off "calendar conversion support"
CTYPE=on "ctype functions"
CURL=on "CURL support"
DBA=off "dba support"
DBASE=off "dBase library support"
DOM=on "DOM support"
EXIF=off "EXIF support"
FILEINFO=off "fileinfo support"
FILTER=on "input filter support"
FRIBIDI=off "FriBidi support"
FTP=off "FTP support"
GD=on "GD library support"
GETTEXT=on "gettext library support"
GMP=off "GNU MP support"
HASH=on "HASH Message Digest Framework"
ICONV=on "iconv support"
IMAP=off "IMAP support"
INTERBASE=off "Interbase 6 database support (Firebird)"
JSON=on "JavaScript Object Serialization support"
LDAP=off "OpenLDAP support"
MBSTRING=on "multibyte string support"
MCRYPT=off "Encryption support"
MHASH=off "Crypto-hashing support"
MING=off "ming shockwave flash support"
MSSQL=off "MS-SQL database support"
MYSQL=off "MySQL database support"
MYSQLI=on "MySQLi database support"
NCURSES=off "ncurses support (CLI only)"
ODBC=off "unixODBC support"
OPENSSL=off "OpenSSL support"
PCNTL=off "pcntl support (CLI only)"
PCRE=on "Perl Compatible Regular Expression support"
PDF=off "PDFlib support (implies GD)"
PDO=on "PHP Data Objects Interface (PDO)"
PDO_SQLITE=on "PDO sqlite driver"
PDO_MYSQL=on "PDO mysql driver"
PGSQL=off "PostgreSQL database support"
POSIX=on "POSIX-like functions"
PSPELL=off "pspell support"
READLINE=off "readline support (CLI only)"
RECODE=off "recode support"
SESSION=on "session support"
SHMOP=off "shmop support"
SIMPLEXML=on "simplexml support"
SNMP=off "SNMP support"
SOAP=off "SOAP support"
SOCKETS=off "sockets support"
SPL=on "Standard PHP Library"
SQLITE=on "sqlite support"
SYBASE_CT=off "Sybase database support"
SYSVMSG=off "System V message support"
SYSVSEM=off "System V semaphore support"
SYSVSHM=off "System V shared memory support"
TIDY=off "TIDY support"
TOKENIZER=on "tokenizer support"
WDDX=off "WDDX support (implies XML)"
XML=on "XML support"
XMLREADER=on "XMLReader support"
XMLRPC=off "XMLRPC-EPI support"
XMLWRITER=on "XMLWriter support"
XSL=off "XSL support (Implies DOM)"
YAZ=off "YAZ support (ANSI/NISO Z39.50)"
ZIP=off "ZIP support"
ZLIB=off "ZLIB support"
===> Use 'make config' to modify these settings

Install mod_fastcgi
# cd /usr/ports/www/mod_fastcgi ; make install

Edit httpd.conf
# vim /usr/local/etc/apache22/httpd.conf
LoadModule fastcgi_module libexec/apache22/mod_fastcgi.so
Include etc/apache22/extra/httpd-mpm.conf

Edit php.conf
# vim /usr/local/etc/apache22/Includes/php.conf
<IfModule prefork.c>
  LoadModule php5_module libexec/apache22/libphp5.so
  AddType application/x-httpd-php .php .html
  AddType application/x-httpd-php-source .phps
</IfModule>

<IfModule worker.c>
  FastCGIExternalServer /usr/local/sbin/php-fpm -socket /tmp/php-fpm.sock -idle-timeout 900
  AddHandler php-fastcgi .php
  Action php-fastcgi /usr/local/sbin/php-fpm.fcgi
  ScriptAlias /usr/local/sbin/php-fpm.fcgi /usr/local/sbin/php-fpm

  <Directory /usr/local/sbin>
    Options ExecCGI FollowSymLinks
    SetHandler fastcgi-script
    Order allow,deny
    Allow from all
  </Directory>
</IfModule>

DirectoryIndex index.php index.html index.htm

Edit php-fpm.conf:
# vim /usr/local/etc/php-fpm.conf
#listen = 127.0.0.1:9000
listen = /tmp/php-fpm.sock

listen.owner = www
listen.group = www
listen.mode = 0660

Edit rc.conf
# vim /etc/rc.conf
## fpm
php_fpm_enable="YES"

## apache
apache22_enable="YES"
apache22_http_accept_enable="YES"

Edit no-accf.conf
# vim /usr/local/etc/apache22/Includes/no-accf.conf
<IfDefine NOHTTPACCEPT>
### make sure you do comment out following two lines
### in order to make accf_http module (the 'httpready' Accept Filter) to work.
#AcceptFilter http none
#AcceptFilter https none
</IfDefine>

Start php-fpm, apache22:
# /usr/local/etc/rc.d/php-fpm start
# /usr/local/etc/rc.d/apache22 start

Make sure it's running as MPM Worker
# httpd -V
Server MPM: Worker

Benchmarking Apache to give us an impression of how our current Apache installation performs
# ab -c 100 -n 10000 http://web-test.local/index.php

測試心得
隨便寫個 <?php echo "hello world"; ?> 來測試

我用 ab -c xx -n xxxx 的方式來測試效能及穩定度 , 分別用 20 , 100 , 500 條連線來測試 50000 次 request

大概可以直接說結果 , 就不看數據了

在 20 及 100 條連線下 , mod_php 的執行時間大約在 3~4 秒 , php-fpm 則在 7~8 秒 , 看樣子 php-fpm 挺鳥的說 ~~

但 500 條連線就見真章了 , mod_php 會很不穩 , 中間會 lag , 所以測試的數據忽上忽下 , 有時 7 秒 , 有時 10 秒甚至 15 秒

而 php-fpm 仍然在 7~8 秒 , 非常穩定

這代表甚麼 ????

Apache worker 模式 + php-fpm 在一個連線數量很多很操的 Server 上會表現得很穩定 , 另外我要說一下 , mod_fastcgi 其實效能並不佳 , 很多測試數據都有說比 Apache 自己寫的 mod_fcgid 差很多 , 我自己也玩過 mod_fcgid + php 也是如此 , 但 mod_fastcgi 表現卻比較穩定 , mod_fcgid 在連線數量多及連續 request 次數多時也會有 lag 情形 , 因此, 有興趣尋求最佳php運作環境的人的可以試試看 lighttpd 或 ngix 甚至是號稱比 lighttpd 及 ngix 快很多的 cherokee 來搭配 php-fpm , 應該會有更棒的表現

後來想想 , hello world 在傳輸的數據太少 , 於是再多測試 <?php phpinfo(); ?> 這個方式

也是用 20 /100/500 條連線來 request 1 萬次

20 條連線時 , mod_php 最佳時間為 6.45 秒 , 而 php-fpm 為 6.42 秒 , 差不多 , 而且都不會 lag

100 條連線時 , mod_php 最佳時間為 6.43 秒 ,php-fpm 為 6.37 秒 , 還是差不多 , 而且都不會 lag

500 條連線時 , mod_php 最佳時間為 6.69 秒 , php-fpm 為 6.42 秒 , 看起來還是一樣 , 但 500 條連線時 , mod_php 發生 lag 情形較多次 , 也就是說可能會看到超過 10 秒以上的時間挺多次的

從上面的測試不難發現 , Apache fork 模式的架構仍有一定的瓶頸 , 而且在實際網站應用上不光只有 php , 還有其他的靜態網頁 , 如果使用 Apache+mod
_php 跑 , 這樣靜態網頁的效能會跟著被拖慢 , 而 Apache worker + php-fpm (或 php fastcgi) 的好處是 , Apache 只把 php 的處理權交出去 , 靜態網頁仍由 Apache 處理 , 這樣在整體效能及記憶體用量都會改善許多

若以單項只跑 php 來看 , mod_php 在一個人不多的網站其實是最快的 , 但當流量大到一定程度 , 除非多買硬體啦 , 若要節省成本 , 採用 FastCGI 架構才是最好的方式

Reference:
http://www.brandonturner.net/blog/2009/07/fastcgi_with_php_opcode_cache/
http://voidweb.com/2010/10/get-high-performance-php-fpm-socket-connections/
http://www.pigo.idv.tw/archives/832
http://benpptung.blogspot.com/2010/11/modfcgi-vs.html

Thursday, May 1, 2014

1萬個小時的錘鍊,造就真正的專精

莫札特(Wolfgang Amadeus Mozart)寫出經典的第九號鋼琴協奏曲時,已持續創作協奏曲10年;

投資大師華倫‧巴菲特(Warren Buffett)早在11歲時,就進行了人生第一筆股票投資交易;

英國搖滾天團披頭四(Beatles)在1964年聲名大噪前,至少已做過1200次現場演出;

微軟(Microsoft)創辦人比爾‧蓋茲(Bill Gates)在上大學前5年,幾乎天天都在寫程式。

這些「成功人士」的共同點是什麼?《異數》(Outliers)作者麥爾坎‧葛拉威爾(Malcolm Gladwell)認為,「成功最重要的關鍵似乎是準備,而非才能。」成功者都在專業生涯剛起步時,就開始密集練習日後藉以揚名立萬的專業,葛拉威爾將此稱之為「1萬小時的努力」。

愈有價值的能力,必須投入愈長時間

葛拉威爾以心理學家艾瑞克森(K. Anders Ericsson)的實驗,說明「勤於練習」的重要。

艾瑞克森把一所音樂學院主修小提琴的學生分成3組,研究發現,「可望成為國際級小提琴家」的第一組學生,在20歲前累計的練習時間已超過1萬小時;「可成為一般職業演奏家」的第二組學生,練習約8000小時;至於「只能當音樂老師」的第三組學生,約練習了4000小時。研究人員最後得出的結論是,「真正的專精,必須經過1萬個小時的錘鍊。」

「1萬小時的錘鍊」並非定律,練習時數究竟要抵達多少小時,才能達到真正的專精,也沒有精確、客觀的標準;然而專注、充分地練習專業技能,確實是成功不可或缺的條件。

聯強國際總裁杜書伍曾說,「愈專業化的東西、愈有價值的能力,學成的困難度愈高,必須投入的時間也愈長。」他並以「公車理論」說明培養實力、等待機會的道理:機會是所有人的公車,不會為了獨獨等你一個人而停下來。若在前往車站的路程中閒散緩慢,當公車駛來時,你仍距離車站20公尺,那是絕對搭不上車的;唯有自始至終保持全速前進的人,才能在公車駛來時,游刃有餘地上車。

熱情和毅力,抵禦練習時的孤寂

成功者通常擁有至少一種專業。所謂「專業」就是精通某一個領域,而精通形同「絕對的稱職」。領導學大師華倫.班尼斯(Warren Bennis)在《領導,不需要頭銜》(On Becoming A Leader)一書中,引述作家喬治‧李奧納德(George Leonard)對於「精通」的定義:「精通建立於勤奮不懈地練習,雖然這也是冒險所在。……無論是運動、藝術或其他工作,被稱為大師的人,都是無視於別人的想法,熱情地投入他們的天職。」

然而,不懈地練習,考驗的是人的意志力與熱情。杜書伍指出,「練習的過程,彷彿摸索著走過一條沒有盡頭的黑暗隧道,恐懼與懷疑交相煎熬下,人們往往會被逼出放棄的衝動。」

然而,熱情和毅力,是成功者的護身符。他們明白,「努力不一定成功,但是不努力一定不會成功」。群聯電子董事長潘健成在一支以他的創業故事為主題的紀錄片中提到,當年公司是以「1個月100萬元」的速度在燒錢,壓力雖然大到讓人心慌,但是基於不想解散團隊的不服輸性格,促使他和事業夥伴加速研發進程,以一天16小時、一周7天的拚勁持續地撰寫程式,終於在一年內做出產品,成功研發出全球第一支單晶片隨身碟。

年僅26歲的華裔設計師吳季剛,因為設計的禮服被美國總統夫人蜜雪兒‧歐巴馬(Michelle Obama)挑中,一炮而紅。看似少年得志的他,其實5歲起就喜歡看婚紗、幫洋娃娃設計衣裳,12歲便正式投入大師門下學習服裝設計。面對旁人異樣的眼光,吳季剛在家人的支持下持續地投入,也讓他比多數設計師同儕,足足多練習了10年。

全力投入,理性應變

在1萬小時的錘鍊過程中,有阻力、有挫折、有變數,除了願意投入時間精神、發揮毅力與熱情之外,要建立起真正的專業,還需要「能夠控制感情,以理性行動」。

《成功長青》(Success Built to Last)一書指出,成功的實踐家熱愛自己的工作,所以願意投入大量時間研究;而專注精神和專業知識,則讓他們能觀察到微妙的產業變化,掌握機會。

日本知名企管顧問大前研一則強調,真正的專業是「即使面對環境變化,也能發揮同樣的專業。」在他眼中,鈴木一朗和松井秀喜這兩位傑出的日籍棒球選手,便稱得上是真正的專業人士。相較於許多在美國大聯盟中「敗下陣來」的日本職棒選手,他們兩人即使去到陌生的異地,不但維持住一貫的高水平,甚至還能夠發揮應變能力,研磨出適應當地的新技能。

換言之,真正專業的企業經理人及領導者,即使面臨多變的環境與激烈的競爭,終究還是能夠臨危不亂,帶領組織走上正確的方向,不會讓自己的能力僅限於一時一地。

二十多年前,中美矽晶董事長盧明光在光寶集團擔任中階主管時,可說是公司的最佳救火隊員,子公司只要出現虧損,就會派他去整頓,而他也每次都不負所託,在一年內轉虧為盈。盧明光笑說,多年來在導電橡膠、連接器、半導體、太陽能、車用電子等產業的不敗經驗,總讓許多人以為他是「福將」,希望邀他入股帶來「幸運」。然而他的成功絕非偶然,而是在於「把公司當成生命一般來經營」的投入精神。

《從A到A+》(From Good to Great)一書中引用了一個經典寓言故事:「狐狸知道很多事情,但刺蝟只知道一件大事。」成功的實踐家,多半都具備刺蝟特質,專心致力於能夠點燃他們熱情的「一件事」,憑著努力、毅力與應變力,在專業的路上不斷突破創新。

Monday, April 28, 2014

print image

using System.Drawing;
using System.Drawing.Printing;

void testPrint()
{
 PrintDocument pd = new PrintDocument();
 pd.PrintPage += (thesender, ev) => {
  ev.Graphics.DrawImage(Image.FromFile("Your Image Path"), 
  //This is to keep image in margins of the Page.
  new PointF(ev.MarginBounds.Left,ev.MarginBounds.Top));
     };
 pd.Print();
}

C# Tutorial - Simple Threaded TCP Server Listen port

In this tutorial I'm going to show you how to build a threaded tcp server with C#. If you've ever worked with Window's sockets, you know how difficult this can sometimes be. However, thanks to the .NET framework, making one is a lot easier than it used to be.

What we'll be building today is a very simple server that accepts client connections and can send and receive data. The server spawns a thread for each client and can, in theory, accept as many connections as you want (although in practice this is limited because you can only spawn so many threads before Windows will get upset).

Let's just jump into some code. Below is the basic setup for our TCP server class.

using System;
using System.Text;
using System.Net.Sockets;
using System.Threading;
using System.Net;

namespace TCPServerTutorial
{
  class Server
  {
    private TcpListener tcpListener;
    private Thread listenThread;

    public Server()
    {
      this.tcpListener = new TcpListener(IPAddress.Any, 3000);
      this.listenThread = new Thread(new ThreadStart(ListenForClients));
      this.listenThread.Start();
    }
  }
}

So here's a basic server class - without the guts. We've got a TcpListener which does a good job of wrapping up the underlying socket communication, and a Thread which will be listening for client connections. You might have noticed the function ListenForClients that is used for our ThreadStart delegate. Let's see what that looks like.

private void ListenForClients()
{
  this.tcpListener.Start();

  while (true)
  {
    //blocks until a client has connected to the server
    TcpClient client = this.tcpListener.AcceptTcpClient();

    //create a thread to handle communication 
    //with connected client
    Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
    clientThread.Start(client);
  }
}

This function is pretty simple. First it starts our TcpListener and then sits in a loop accepting connections. The call to AcceptTcpClient will block until a client has connected, at which point we fire off a thread to handle communication with our new client. I used a ParameterizedThreadStart delegate so I could pass the TcpClient object returned by the AcceptTcpClient call to our new thread.

The function I used for the ParameterizedThreadStart is called HandleClientComm. This function is responsible for reading data from the client. Let's have a look at it.

private void HandleClientComm(object client)
{
  TcpClient tcpClient = (TcpClient)client;
  NetworkStream clientStream = tcpClient.GetStream();

  byte[] message = new byte[4096];
  int bytesRead;

  while (true)
  {
    bytesRead = 0;

    try
    {
      //blocks until a client sends a message
      bytesRead = clientStream.Read(message, 0, 4096);
    }
    catch
    {
      //a socket error has occured
      break;
    }

    if (bytesRead == 0)
    {
      //the client has disconnected from the server
      break;
    }

    //message has successfully been received
    ASCIIEncoding encoder = new ASCIIEncoding();
    System.Diagnostics.Debug.WriteLine(encoder.GetString(message, 0, bytesRead));
  }

  tcpClient.Close();
}

The first thing we need to do is cast client as a TcpClient object since the ParameterizedThreadStart delegate can only accept object types. Next, we get the NetworkStream from the TcpClient, which we'll be using to do our reading. After that we simply sit in a while true loop reading information from the client. The Read call will block indefinitely until a message from the client has been received. If you read zero bytes from the client, you know the client has disconnected. Otherwise, a message has been successfully received from the server. In my example code, I simply convert the byte array to a string and push it to the debug console. You will, of course, do something more interesting with the data - I hope. If the socket has an error or the client disconnects, you should call Close on the TcpClient object to free up any resources it was using.

Believe it or not, that's pretty much all you need to do to create a threaded server that accepts connections and reads data from clients. However, a server isn't very useful if it can't send data back, so let's look at how to send data to one of our connected clients.

NetworkStream clientStream = tcpClient.GetStream();
ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Client!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();

Do you remember the TcpClient object that was returned from the call AcceptTcpClient? Well, that's the object we'll be using to send data back to that client. That being said, you'll probably want to keep those objects around somewhere in your server. I usually keep a collection of TcpClient objects that I can use later. Sending data to connected clients is very simple. All you have to do is call Write on the the client's NetworkStream object and pass it the byte array you'd like to send.

Your TCP server is now finished. The hard part is defining a good protocol to use for sending information between the client and server. Application level protocols are generally unique for application, so I'm not going to go into any details - you'll just have to invent you're own.

But what use is a server without a client to connect to it? This tutorial is mainly about the server, but here's a quick piece of code that shows you how to set up a basic TCP connection and send it a piece of data.

TcpClient client = new TcpClient();

IPEndPoint serverEndPoint = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 3000);

client.Connect(serverEndPoint);

NetworkStream clientStream = client.GetStream();

ASCIIEncoding encoder = new ASCIIEncoding();
byte[] buffer = encoder.GetBytes("Hello Server!");

clientStream.Write(buffer, 0 , buffer.Length);
clientStream.Flush();

The first thing we need to do is get the client connected to the server. We use the TcpClient.Connect method to do this. It needs the IPEndPoint of our server to make the connection - in this case I connect it to localhost on port 3000. I then simply send the server the string "Hello Server!".

One very important thing to remember is that one write from the client or server does not always equal one read on the receiving end. For instance, your client could send 10 bytes to the server, but the server may not get all 10 bytes the first time it reads. Using TCP, you're pretty much guaranteed to eventually get all 10 bytes, but it might take more than one read. You should keep that in mind when designing your protocol.

That's it! Now get out there and clog the tubes with your fancy new C# TCP servers.

Reference:
http://tech.pro/tutorial/704/csharp-tutorial-simple-threaded-tcp-server

10001 件資工系畢業前一定要做的事

畢業季到了,看著學長姐紛紛離開校園的溫室,準備前去挑戰現實世界的殘酷,你心中或許會想,輪到我時,我準備好了嗎?這邊幫你準備了 10001 件在離開校園前,你應該嘗試過的事情。
00000 擁有你自己的網域 — 買 .com 和 .com.tw 的網域有各自的竅門,如何找到最划算的價錢,你應該要知道
00001 租用你自己的雲端主機 — AWS 第一年幾乎是免費的,EC2 和 S3 是兩個你至少要摸熟的服務
00010 安裝 Apache 伺服器軟體 — 學著設定 httpd.conf,例如把 www.domain.com 轉到 domain.com (台灣 90% 的網站都忘了做這件事)
00011 安裝 WordPress,經營一個網誌 — 長期經營網誌有很多好處,況且對於程式人員來說,寫作能力是最重要的技能之一
00100 用 Ruby on Rails 寫出一個產品 — 我認為 Rails 將會取代 LAMP 的地位,現在缺 Ruby 工程師的比缺 LAMP 的還多,而且都是一些非常棒的新創團隊,我鼓勵你把這個框架學好
00101 幫同學解決一個實際的問題 — 去跟非資工系的同學、朋友、親戚聊天,找出他們生活、工作、社團有什麼實際的問題,你可以用程式幫他們解決的,然後實際做出這個網站給他們使用
00110 寫一個 iOS/Android App — 如果上面這個問題,透過 Smartphone App 可以解決得更好,那就寫一個 iPhone/Android 給他們 (台大的學生可以考慮去上我的合夥人 Prof. Mike Chen 的智慧手機開發課)
00111 實際使用 Facebook API — 用 Facebook Connect 來讓使用者快速登入你的網站,並且拿到他們的 Email 和好友名單,再想辦法利用這兩個資料給他們更好的服務
01000 實際使用 MongoDB (或是其他 NoSQL) — 學校教了很多 RDBMS,但是你要知道現在有很多時候 NoSQL 更符合需求,尤其是大規模網站
01001 把你的網站放上 AdSense — 雖然沒辦法賺大錢,但是你會因此更了解網路廣告的各種內幕
01010 讀很多別人寫的程式碼、文章和書 — 寫程式和寫作進步的方法,除了多練習,就是多讀別人的作品
01011 下載並 Compile 一個複雜的 Open Source 專案 — 像是 OpenSim 或是Matterhorn
01100 貢獻給一個 Open Source 專案 — Open Source 界有他們的文化,跟他們實際協做過,你才能了解
01101  學會用 packet sniffer — 聽聽看你愛玩的遊戲,是怎麼跟它的主機溝通的,你會學到很多
01110 設定你的 DSL Router讓家裡電腦當伺服器 — 你會對 TCP/UDP ports 有更多了解
01111 用 map-reduce 分析資料 — 這是現在最最熱門的題目,你應該要試試 (從這裡開始)
10000 去當暑期實習生 — 暑假來了,實際去公司上班兩個月,看看真實世界是長什麼樣子吧!新創公司尤其是你的好選擇,因為你將可以摸到更多好玩的東西 (不知道要去哪裡?寫信來,我幫你介紹: mr.jamie.blog [at] gmail.com)
10001 去跟 10 個學長姐聊聊 — 在你決定要繼續攻碩士、就業還是創業前,去跟 10 個已經畢業的資工系學長姐聊聊,看看他們都在做什麼,有什麼事情他們後悔當初沒學好,有什麼事情他們覺得你可以考慮去做。不要悶著頭聽同學們的建議做決定,他們和你一樣不知道自己在做什麼。
以上,希望對於正在念資工系的你們有幫助。

http://mrjamie.cc/2011/06/27/things-all-cs-students-should-do/

Friday, April 25, 2014

WIFI issue on Windows Mobile Motorola MC9500 Series

If you found WIFI problem with your handheld scanner Motorola MC3190 this article could be the solution for you. We have already 10 monochrome scanners to scan garment in the factory. Recently we buy 6 units of Motorola MC3190 colour with Win CE6.0 as its operating system. Although we happy with new colour handheld scanner, we have a problem with it's WIFI.

When we do cold boot (press 1+9+power) the wifi is always disabled, we have to enable it first to use it. This is not acceptable because user will have to access windows first to enable the wifi.

After googling i found that the problem is not unique, many people having the same problem. Searching more i found posting about this problem from .Fret Developer (http://dotfret.blogspot.com/2010/10/wireless-radio-disabled-on-cold-boot-of.html). The blog owner is a savvy .NET developer.

" After a cold boot of your Motorola / Symbol MC9500 series device, if you find that your wireless radio is disabled, create the following .reg file and add it to the \Application folder on the device;"

REGEDIT4

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\WLAN]
"InitialState"=dword:00000000

It's easy to follow and it worked.

Several days later i got a reg file from our supplier that came from Motorola. This file called "fusion on.reg" and same with above direction, it must be put into application folder of scanner.

REGEDIT4

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\WLAN]
"InitialState"=dword:00000000
"Prefix"="WLP"
"Dll"="PmProxy.Dll"
"Order"=dword:00000008
"Index"=dword:00000001
"DeviceArrayIndex"=dword:00000004
"WLANSlot"=dword:00000000
"Flags"=dword:00000008
"IClass"=hex(7):\
7B,41,33,32,39,34,32,42,37,2D,39,32,30,43,2D,34,38,36,62,2D,42,30,45,36,\
2D,39,32,41,37,30,32,41,39,39,42,33,35,7D,00,7B,66,38,61,36,62,61,39,38,\
2D,30,38,37,61,2D,34,33,61,63,2D,61,39,64,38,2D,62,37,66,31,33,63,35,62,\
61,65,33,31,7D,00,7B,39,34,31,30,37,44,37,30,2D,33,34,43,46,2D,34,31,39,\
61,2D,42,41,42,41,2D,31,45,35,30,39,36,31,38,35,33,34,37,7D,00,00
"FriendlyName"="WLAN Proxy Driver for Motorola WLAN Adapter"
"SupportedStates"=dword:00000011
"InitFlags"=dword:00000000
"SlotResetOnResume"=dword:00000000
"SlotResetWait"=dword:000001F4

[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\WLAN\ActivityEvents]
"PowerManager/SystemIdleTimerReset"=""


This solution is also solved my problem. Albeit I'm not really know the different but since it come from my supplier which is Motorola distributor and it seems more complex than the first one from .fret blog i decided to use this file.

Once again without .fret blog i may not found the solution quickly. Thank you.

http://freestuff2.hubpages.com/hub/Motorola-MC3190-WIFI-Problem-Solved

Wednesday, April 23, 2014

_default_ VirtualHost overlap on port 443, the first has precedence

Problem:
# /usr/local/etc/rc.d/apache22 onerestart
Performing sanity check on apache22 configuration:
[Wed Apr 23 15:43:04 2014] [warn] _default_ VirtualHost overlap on port 443, the first has precedence
Syntax OK

Solution:

Add this line to your httpd-ssl.conf:

NameVirtualHost *:443