<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>程式設計 遇上 小提琴 &#187; 可攜性</title>
	<atom:link href="http://blog.ez2learn.com/tag/%E5%8F%AF%E6%94%9C%E6%80%A7/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.ez2learn.com</link>
	<description>Victor&#039;s個人部落格，關於程式設計與小提琴</description>
	<lastBuildDate>Thu, 26 Aug 2010 10:49:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>如何評估比較程式語言</title>
		<link>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/</link>
		<comments>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/#comments</comments>
		<pubDate>Thu, 07 Jan 2010 19:32:47 +0000</pubDate>
		<dc:creator>victor</dc:creator>
				<category><![CDATA[Python]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[可寫性]]></category>
		<category><![CDATA[可讀性]]></category>
		<category><![CDATA[可攜性]]></category>
		<category><![CDATA[程式語言]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[programming language]]></category>

		<guid isPermaLink="false">http://blog.ez2learn.com/?p=928</guid>
		<description><![CDATA[有人提到以過去的觀點來看現在的PHP是不公平的，確實我有好一陣子沒有碰PHP，對於新版的PHP並不瞭解，因此我花了一些時間檢視新的PHP規格，的確新版的PHP遠比我預料的進步許多，很多之前提到的問題有所改善，我承認上一篇文章說PHP很爛是在發洩過去對於PHP的種種不滿，有人認為程式語言沒有好壞，全部都事在人為，而我認為程式語言的好壞有主觀也有客觀的部份，當你討厭或喜歡一個程式語言一定有某些原因，但就客觀的來看語言的設計來講，PHP在早期真的是爛得一榻糊塗，是公認的爛，但是在當時少有選擇，能選的工具不多，就只有PHP，在累積夠久的不滿後就會一次暴發開來，對於現在的PHP5.3還有未來的PHP6而言，他已經跳離了以前的單純語言設計上的爛，往更好的方向前進，我能說PHP的壞話少了很多，因為當語言層面的問題大部份都解決了，接著就是哲學和個人喜好的問題了，對與目前和新版的PHP的誤解在這邊說聲抱歉 所以這篇我想說的，怎樣看客觀地評估一款語言的好壞，還有主觀地評估好與壞，很多人說程式語言沒有好與壞，只有適合和不適合，基本上我不認同這樣的說法，如果說兩種差別很大用途不同的語言拿來一起比較就很奇怪，但是如果是性質接近的語言都符合你需求，就可以做好壞的比較，不然你要怎麼做選擇? 就如同我們買車子好了，你的目的是載貨，買的自然是卡車、貨車，但是如果是轎車呢? 就算是卡車也有選擇的，程式語言也一樣，目前大部份人所見到的程式語言，都是所謂的"通用目的"語言，也就是說這樣的語言沒有預設任何用途，基本上他可以拿來做任何用途，很多人因為不知道要從何比較起，所以都說程式語言沒有好壞之分，只有適合和不適合，如果有一堆工具都適合，既然沒有好壞之分，那你又該如何做出進一步的評估與選擇? 適不適合不就是透過比較而來的嗎? 不比較怎麼知道適不適合? 這不是自相矛盾嗎? 只靠喜好嗎? 閉著眼睛亂選? 大家都知道車子我們可以比較它的馬力、耗油、安全評等，但是大多數人不知道程式語言該比較些什麼，而我今天所要說的，就是程式語言該拿什麼來比較 客觀的評估條件 首先，客觀的評估條件並不是完全客觀的，在某些情況它會帶有主觀色彩，例如一個語法的可讀性如何，這就帶有某種程度的主觀，事實上有一個領域是在探討這些問題的，在資訊工程系開的一門課叫「程式語言」就有某部份在討論這些，但是對於這部份沒有很深入，而關於這些條件應該有更嚴僅學術上的方式來對這些條件進行評估，但是那超出我的知識範圍，我就我所知道的來說 可讀性 可讀性是指一個程式語言寫出來的語句是否容易閱讀 可讀性是程式語言很重要的一個優劣的參考指標，因為有一個事實就是 程式被讀比被寫還多次 一個程式的可讀性，關係到維護的人能否輕易的瞭解程式語言所表達程式的意圖，如果維護的人難以理解某段程式所要表達的事情，那麼這些程式就難以被維護，軟體工程中有個很重要的概念就是，程式開發的成本其實只佔一小部份，而維護其實所花的成本會比開發來得多，在這樣的情況下，如果寫出來的程式難以被讀懂，那麼接手的人將難以進行維護，如此一來可能要面臨整個程式重寫的情況，會使得維護的成本大大增加，程式碼也失去了重覆利用的價值，所以可讀性對於一款程式語言的好壞來說是很重要的一個指標 為了說明可讀性爛的程式語言，我找來最極端的例子，Brainfuck是一款以圖靈機為模型，所做出來最小化的程式語言，它所寫出來的Helloworld程式如下 ++++++++++[&#62;+++++++&#62;++++++++++&#62;+++&#62;+&#60;&#60;&#60;&#60;-] &#62;++.&#62;+.+++++++..+++.&#62;++.&#60;&#60;+++++++++++++++. &#62;.+++.&#8212;&#8212;.&#8212;&#8212;&#8211;.&#62;+.&#62;. 我想應該沒有太多人會反對我說Brainfuck可讀性很差 XD 我喜歡極端的例子，再來一個國際混亂碼大賽的參賽作品，這是一個要將程式寫到別人看不懂，但又要能夠運作，而且要夠創意的比賽，所以寫出來的程式都是可讀性0分的程式，下面這個是可以計算圓周率的程式 #define _ -F&#60;00&#124;&#124;--F-OO--; int F=00,OO=00;main&#40;&#41;&#123;F_OO&#40;&#41;;printf&#40;&#34;%1.3f\n&#34;,4.*-F/OO/OO&#41;;&#125;F_OO&#40;&#41; &#123; _-_-_-_ _-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_-_-_-_-_ _-_-_-_-_-_-_-_ _-_-_-_ &#125; 當然，這是故意寫出來難懂的例子，有些程式語言天生寫出來的程式就較難懂，或是較容易寫出難懂的程式，舉個例子，Perl程式可讀性和Python比較起來就差很多，下面兩隻程式的目的都一樣，是一隻簡單的Web Proxy程式，Python版本是我參照Perl版寫出來的，特意按照同樣的架構下去寫，目的就是要能容易做比較 Perl版: #!/usr/bin/perl #------------------------------------------------------------------------- #-- proxy.pl - [...]]]></description>
			<content:encoded><![CDATA[<p>有人提到以過去的觀點來看現在的PHP是不公平的，確實我有好一陣子沒有碰PHP，對於新版的PHP並不瞭解，因此我花了一些時間檢視新的PHP規格，的確新版的PHP遠比我預料的進步許多，很多之前提到的問題有所改善，我承認上一篇文章說PHP很爛是在發洩過去對於PHP的種種不滿，有人認為程式語言沒有好壞，全部都事在人為，而我認為程式語言的好壞有主觀也有客觀的部份，當你討厭或喜歡一個程式語言一定有某些原因，但就客觀的來看語言的設計來講，PHP在早期真的是爛得一榻糊塗，是公認的爛，但是在當時少有選擇，能選的工具不多，就只有PHP，在累積夠久的不滿後就會一次暴發開來，對於現在的PHP5.3還有未來的PHP6而言，他已經跳離了以前的單純語言設計上的爛，往更好的方向前進，我能說PHP的壞話少了很多，因為當語言層面的問題大部份都解決了，接著就是哲學和個人喜好的問題了，對與目前和新版的PHP的誤解在這邊說聲抱歉</p>
<p>所以這篇我想說的，怎樣看客觀地評估一款語言的好壞，還有主觀地評估好與壞，很多人說程式語言沒有好與壞，只有適合和不適合，基本上我不認同這樣的說法，如果說兩種差別很大用途不同的語言拿來一起比較就很奇怪，但是如果是性質接近的語言都符合你需求，就可以做好壞的比較，不然你要怎麼做選擇? 就如同我們買車子好了，你的目的是載貨，買的自然是卡車、貨車，但是如果是轎車呢? 就算是卡車也有選擇的，程式語言也一樣，目前大部份人所見到的程式語言，都是所謂的"通用目的"語言，也就是說這樣的語言沒有預設任何用途，基本上他可以拿來做任何用途，很多人因為不知道要從何比較起，所以都說程式語言沒有好壞之分，只有適合和不適合，如果有一堆工具都適合，既然沒有好壞之分，那你又該如何做出進一步的評估與選擇? 適不適合不就是透過比較而來的嗎? 不比較怎麼知道適不適合? 這不是自相矛盾嗎? 只靠喜好嗎? 閉著眼睛亂選?  大家都知道車子我們可以比較它的馬力、耗油、安全評等，但是大多數人不知道程式語言該比較些什麼，而我今天所要說的，就是程式語言該拿什麼來比較</p>
<p><span id="more-928"></span></p>
<h2>客觀的評估條件</h2>
<p>首先，客觀的評估條件並不是完全客觀的，在某些情況它會帶有主觀色彩，例如一個語法的可讀性如何，這就帶有某種程度的主觀，事實上有一個領域是在探討這些問題的，在資訊工程系開的一門課叫「程式語言」就有某部份在討論這些，但是對於這部份沒有很深入，而關於這些條件應該有更嚴僅學術上的方式來對這些條件進行評估，但是那超出我的知識範圍，我就我所知道的來說</p>
<h3>可讀性</h3>
<p>可讀性是指一個程式語言寫出來的語句是否容易閱讀</p>
<p>可讀性是程式語言很重要的一個優劣的參考指標，因為有一個事實就是</p>
<blockquote><p>程式被讀比被寫還多次</p></blockquote>
<p>一個程式的可讀性，關係到維護的人能否輕易的瞭解程式語言所表達程式的意圖，如果維護的人難以理解某段程式所要表達的事情，那麼這些程式就難以被維護，軟體工程中有個很重要的概念就是，程式開發的成本其實只佔一小部份，而維護其實所花的成本會比開發來得多，在這樣的情況下，如果寫出來的程式難以被讀懂，那麼接手的人將難以進行維護，如此一來可能要面臨整個程式重寫的情況，會使得維護的成本大大增加，程式碼也失去了重覆利用的價值，所以可讀性對於一款程式語言的好壞來說是很重要的一個指標</p>
<p>為了說明可讀性爛的程式語言，我找來最極端的例子，<a href="http://zh.wikipedia.org/zh-tw/Brainfuck">Brainfuck</a>是一款以<a href="http://zh.wikipedia.org/zh-tw/%E5%9B%BE%E7%81%B5%E6%9C%BA">圖靈機</a>為模型，所做出來最小化的程式語言，它所寫出來的Helloworld程式如下</p>
<blockquote><p>++++++++++[&gt;+++++++&gt;++++++++++&gt;+++&gt;+&lt;&lt;&lt;&lt;-]<br />
&gt;++.&gt;+.+++++++..+++.&gt;++.&lt;&lt;+++++++++++++++.<br />
&gt;.+++.&#8212;&#8212;.&#8212;&#8212;&#8211;.&gt;+.&gt;.</p></blockquote>
<p>我想應該沒有太多人會反對我說Brainfuck可讀性很差 XD</p>
<p>我喜歡極端的例子，再來一個<a href="http://zh.wikipedia.org/zh-tw/%E5%9B%BD%E9%99%85C%E8%AF%AD%E8%A8%80%E6%B7%B7%E4%B9%B1%E4%BB%A3%E7%A0%81%E5%A4%A7%E8%B5%9B">國際混亂碼大賽</a>的參賽作品，這是一個要將程式寫到別人看不懂，但又要能夠運作，而且要夠創意的比賽，所以寫出來的程式都是可讀性0分的程式，下面這個是可以計算圓周率的程式<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="c" style="font-family:monospace;"> <span style="color: #339933;">#define _ -F&lt;00||--F-OO--;</span>
 <span style="color: #993333;">int</span> F<span style="color: #339933;">=</span><span style="color: #208080;">00</span><span style="color: #339933;">,</span>OO<span style="color: #339933;">=</span><span style="color: #208080;">00</span><span style="color: #339933;">;</span>main<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#123;</span>F_OO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>printf<span style="color: #009900;">&#40;</span><span style="color: #ff0000;">&quot;%1.3f<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">,</span><span style="color:#800080;">4.</span><span style="color: #339933;">*-</span>F<span style="color: #339933;">/</span>OO<span style="color: #339933;">/</span>OO<span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span><span style="color: #009900;">&#125;</span>F_OO<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
 <span style="color: #009900;">&#123;</span>
             _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
        _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
     _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
   _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
  _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
   _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
     _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
         _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
             _<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_<span style="color: #339933;">-</span>_
 <span style="color: #009900;">&#125;</span></pre></div></div>

<p></code><br />
當然，這是故意寫出來難懂的例子，有些程式語言天生寫出來的程式就較難懂，或是較容易寫出難懂的程式，舉個例子，Perl程式可讀性和Python比較起來就差很多，下面兩隻程式的目的都一樣，是一隻簡單的Web Proxy程式，Python版本是我參照Perl版寫出來的，特意按照同樣的架構下去寫，目的就是要能容易做比較</p>
<p>Perl版:<br />
<code></p>

<div class="wp_syntax"><div class="code"><pre class="perl" style="font-family:monospace;"><span style="color: #666666; font-style: italic;">#!/usr/bin/perl</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     proxy.pl    -  A simple http proxy server.                      --</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	The original program was from:</span>
<span style="color: #666666; font-style: italic;">#		http://www.cis.upenn.edu/sdt/proxy.pl</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	The original program employs the basic socket library, which</span>
<span style="color: #666666; font-style: italic;">#		seems hard to understand for some beginners.</span>
<span style="color: #666666; font-style: italic;">#	That is why I modify it  by employing the </span>
<span style="color: #666666; font-style: italic;">#		IO::Socket::INET</span>
<span style="color: #666666; font-style: italic;">#</span>
<span style="color: #666666; font-style: italic;">#	jay.s.liu@gmail.com</span>
<span style="color: #666666; font-style: italic;">#	Apr. 17, 2006</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     To run, type   proxy.pl [port-number]   at the shell prompt.    --</span>
<span style="color: #666666; font-style: italic;">#--     Default port number is 5364.                                    --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">use</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span><span style="color: #339933;">;</span>
<span style="color: #000066;">srand</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">time</span><span style="color: #339933;">||</span><span style="color: #0000ff;">$$</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Define a friendly exit handler</span>
<span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span><span style="color: #ff0000;">'KILL'</span><span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span>QUIT<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SIG</span><span style="color: #009900;">&#123;</span>INT<span style="color: #009900;">&#125;</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">'exit_handler'</span><span style="color: #339933;">;</span>
<span style="color: #000000; font-weight: bold;">sub</span> exit_handler <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span> --- Proxy server is dying ...<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$SOCKET</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#Disable buffering</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##--- Step 1 : Create Socket ---##	</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Get the port number form commemd line	</span>
<span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=</span> <span style="color: #000066;">shift</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">@ARGV</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>								
<span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">5364</span> <span style="color: #b1b100;">unless</span> <span style="color: #0000ff;">$proxy_port</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/\d+/</span><span style="color: #339933;">;</span>		
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Create a socket that listens to a specific port</span>
<span style="color: #0000ff;">&amp;listen_to_port</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$proxy_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>			
&nbsp;
<span style="color: #0000ff;">$local_host</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #0000ff;">$local_host_ip</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">sockhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Proxy server running on $local_host( $local_host_ip ) port: $proxy_port <span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Loop forever taking requests as they come</span>
<span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##--- Step 2 : Wait for request ---##</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Waiting to be of service ...<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$CHILD</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$SOCKET</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">accept</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;accept $!&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#--- Get the ip address of clinet</span>
    <span style="color: #0000ff;">$inetaddr</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>					 
    <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerport</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Connection from &quot;</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$inetaddr</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;  port: $port <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Fork a subprocess to handle request.</span>
<span style="color: #666666; font-style: italic;">#---  Parent proces continues listening.</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">fork</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">wait</span><span style="color: #339933;">;</span>           <span style="color: #666666; font-style: italic;"># For now we wait for the child to finish</span>
        <span style="color: #b1b100;">next</span><span style="color: #339933;">;</span>           <span style="color: #666666; font-style: italic;"># We wait so that printouts don't mix</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 3 : Read first line of request and analyze it. ---##</span>
<span style="color: #666666; font-style: italic;">#---  Return and edited version of the first line and the request method.</span>
  <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">&amp;analyze_request</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 4 : Send request to remote host ---##</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-- Read HTTP header and Send it to remote host</span>
    <span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">next</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/Proxy-Connection:/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#discard the line which begins with the string &quot;/Proxy-Connection:/&quot;</span>
	<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009966; font-style: italic;">/Content-length:(.*)/i</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
	    <span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$1</span><span style="color: #339933;">;</span>
	<span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>	<span style="color: #666666; font-style: italic;">#exit loop if the line only contains space and null character</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#Read HTTP content and Send it to remote host</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$method</span> <span style="color: #b1b100;">eq</span> <span style="color: #ff0000;">&quot;POST&quot;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>			
		<span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$contentLength</span> <span style="color: #339933;">!=</span> <span style="color: #cc66cc;">0</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
		    <span style="color: #000066;">read</span> <span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$data</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$contentLength</span><span style="color: #339933;">;</span>
		<span style="color: #009900;">&#125;</span> 
		<span style="color: #b1b100;">else</span> <span style="color: #009900;">&#123;</span>
		    <span style="color: #0000ff;">$data</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;;</span>
		<span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;POST body: $data&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #0000ff;">$data</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066;">print</span> <span style="color: #0000ff;">$URL</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">##---  Step 5 : Wait for response and transfer it to requestor. ---##	</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Done sending. Response: <span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$header</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">$text</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$URL</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$header</span> <span style="color: #339933;">||</span> <span style="color: #0000ff;">$text</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>      <span style="color: #666666; font-style: italic;"># Only print header &amp; text lines to STDOUT</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$header</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
                <span style="color: #0000ff;">$header</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">0</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">#           if ($header &amp;&amp; $_ =~ /^Content-type: text/) {</span>
<span style="color: #666666; font-style: italic;">#               $text = 1;</span>
<span style="color: #666666; font-style: italic;">#           }</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>                       <span style="color: #666666; font-style: italic;"># Exit from child process</span>
<span style="color: #009900;">&#125;</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     analyze_request                                                 --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Analyze a new request.  First read in first line of request.    --</span>
<span style="color: #666666; font-style: italic;">#--     Read URL from it, process URL and open connection.              --</span>
<span style="color: #666666; font-style: italic;">#--     Return an edited version of the first line and the request      --</span>
<span style="color: #666666; font-style: italic;">#--     method.                                                         --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> analyze_request <span style="color: #009900;">&#123;</span>
<span style="color: #666666; font-style: italic;">#---  Read first line of HTTP request</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$first</span> <span style="color: #339933;">=</span> <span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;;</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$url</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #339933;">|</span><span style="color: #009900;">&#40;</span>http<span style="color: #339933;">://</span><span style="color: #0000ff;">\S</span><span style="color: #339933;">+</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">|</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Request for URL:  $url <span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Check if first line is of the form GET http://host-name ...</span>
    <span style="color: #b1b100;">my</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_host</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> 
        <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #000066;">m</span><span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span>GET<span style="color: #339933;">|</span>POST<span style="color: #339933;">|</span>HEAD<span style="color: #009900;">&#41;</span> http<span style="color: #339933;">://</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#91;</span><span style="color: #339933;">^/:</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">+</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">:?</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">\d</span><span style="color: #339933;">*</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">!</span> <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  If not, bad request.</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$remote_host</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Invalid HTTP request from &quot;</span><span style="color: #339933;">,</span><span style="color: #0000ff;">$inetaddr</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #ff0000;">&quot;I don't understand your request.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  If requested URL is the proxy server then ignore request</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$local_host</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
	<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
	<span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$local_ip</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_host</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">#Get localhost ip (packed imformation)</span>
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$remote_ip</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_host</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>		<span style="color: #666666; font-style: italic;">#Get remote ip (packed imformation)</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_ip</span> <span style="color: #b1b100;">eq</span> <span style="color: #0000ff;">$local_ip</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_port</span> <span style="color: #b1b100;">eq</span> <span style="color: #0000ff;">$proxy_port</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$first</span><span style="color: #339933;">;</span>
        <span style="color: #b1b100;">while</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">&lt;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #339933;">&gt;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #000066;">print</span> <span style="color: #0000ff;">$_</span><span style="color: #339933;">;</span>
            <span style="color: #b1b100;">last</span> <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">/^[\s\x00]*$/</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #009900;">&#125;</span>
        <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot; --- Connection to proxy server ignored.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">print</span> <span style="color: #0000ff;">$CHILD</span> <span style="color: #ff0000;">&quot;It's not nice to make me loop on myself!.<span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">close</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$CHILD</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000066;">exit</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Setup connection to target host and send request</span>
    <span style="color: #0000ff;">$remote_port</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">&quot;http&quot;</span> <span style="color: #b1b100;">unless</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #0000ff;">&amp;open_connection</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$URL</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_host</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$remote_port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#---  Remove remote hostname from URL</span>
        <span style="color: #0000ff;">$first</span> <span style="color: #339933;">=~</span> <span style="color: #009966; font-style: italic;">s/http:\/\/[^\/]+//</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$first</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$method</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$URL</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     listen_to_port($SOCKET, $port)                                   --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Create a socket that listens to a specific port                 --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> listen_to_port <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$max_requests</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$return_value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #0000ff;">$max_requests</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">30</span><span style="color: #339933;">;</span>          <span style="color: #666666; font-style: italic;"># Max number of outstanding requests</span>
&nbsp;
	<span style="color: #666666; font-style: italic;">#--- Get localhost name</span>
	<span style="color: #0000ff;">$local_hostname</span> <span style="color: #339933;">=</span> <span style="color: #ff0000;">`hostname`</span><span style="color: #339933;">;</span>	
	<span style="color: #000066;">chop</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$local_hostname</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
    <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span> <span style="color: #009900;">&#40;</span>
    						LocalHost <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$local_hostname</span><span style="color: #339933;">,</span>
							LocalPort <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span>
							Proto <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'tcp'</span><span style="color: #339933;">,</span>
							Listen <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$max_request</span><span style="color: #339933;">,</span>
							ReuseAddr <span style="color: #339933;">=&gt;</span> <span style="color: #cc66cc;">1</span>
                                                       <span style="color: #009900;">&#41;</span>  <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;socket: $!&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span> 
    <span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>                             <span style="color: #666666; font-style: italic;"># Disable buffering on socket.</span>
    <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #666666; font-style: italic;">#--     open_connection($SOCKET, $remote_hostname, $port)                --</span>
<span style="color: #666666; font-style: italic;">#--                                                                     --</span>
<span style="color: #666666; font-style: italic;">#--     Create a socket that connects to a certain host                 --</span>
<span style="color: #666666; font-style: italic;">#-------------------------------------------------------------------------</span>
<span style="color: #000000; font-weight: bold;">sub</span> open_connection <span style="color: #009900;">&#123;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_hostname</span><span style="color: #339933;">,</span> <span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">@_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">1</span><span style="color: #339933;">,</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$return_value</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #666666; font-style: italic;">#-- Get the port number by service name</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span> <span style="color: #339933;">!~</span> <span style="color: #009966; font-style: italic;">/^\d+$/</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">getservbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span> <span style="color: #ff0000;">&quot;tcp&quot;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">2</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
        <span style="color: #0000ff;">$port</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">80</span> <span style="color: #b1b100;">unless</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$port</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>				<span style="color: #666666; font-style: italic;">#If the service name is not valid, give it a default number(80)</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #b1b100;">my</span> <span style="color: #0000ff;">$remote_addr</span> <span style="color: #339933;">=</span> <span style="color: #009900;">&#40;</span><span style="color: #000066;">gethostbyname</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_hostname</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">4</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">;</span>
    <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #0000ff;">$remote_addr</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
        <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;Unknown host: $remote_hostname&quot;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
&nbsp;
&nbsp;
    <span style="color: #666666; font-style: italic;">#print &quot;Connecting to $remote_hostname port $port.\n\n&quot;;</span>
    <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> IO<span style="color: #339933;">::</span><span style="color: #006600;">Socket</span><span style="color: #339933;">::</span><span style="color: #006600;">INET</span> <span style="color: #009900;">&#40;</span>
    						PeerAddr <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$remote_hostname</span><span style="color: #339933;">,</span>
							PeerPort <span style="color: #339933;">=&gt;</span> <span style="color: #0000ff;">$port</span><span style="color: #339933;">,</span>
							Proto <span style="color: #339933;">=&gt;</span> <span style="color: #ff0000;">'tcp'</span>
                            <span style="color: #009900;">&#41;</span> <span style="color: #339933;">||</span> <span style="color: #000066;">die</span> <span style="color: #ff0000;">&quot;socket: $!&quot;</span><span style="color: #339933;">;</span>   
&nbsp;
	<span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$remote_ip</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #339933;">-&gt;</span><span style="color: #006600;">peerhost</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>									   
    <span style="color: #000066;">print</span> <span style="color: #ff0000;">&quot;Connecting to $remote_ip port $port.<span style="color: #000099; font-weight: bold;">\n</span><span style="color: #000099; font-weight: bold;">\n</span>&quot;</span><span style="color: #339933;">;</span>								
&nbsp;
    <span style="color: #000066;">local</span> <span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">=</span> <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$_</span><span style="color: #009900;">&#91;</span><span style="color: #cc66cc;">0</span><span style="color: #009900;">&#93;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>  
    <span style="color: #0000ff;">$|</span> <span style="color: #339933;">=</span> <span style="color: #cc66cc;">1</span><span style="color: #339933;">;</span>                             <span style="color: #666666; font-style: italic;"># Disable buffering on socket.</span>
    <span style="color: #000066;">select</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">$cur</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p></code></p>
<p>Python版:</p>
<p><code></p>

<div class="wp_syntax"><div class="code"><pre class="python" style="font-family:monospace;"><span style="color: #483d8b;">&quot;&quot;&quot;This is a simple HTTP proxy written in Python that imitate the Perl one:
&nbsp;
http://liuj.fcu.edu.tw/net_pg/proxy-stu.pl.html
&nbsp;
I wrote this in Python for classmates to compare to the one in Perl, because the 
readability of Perl is awful. You can see the readaibility is much better than 
the Perl one. You can also read this article:
&nbsp;
http://www.garshol.priv.no/download/text/perl.html
&nbsp;
to see what's wrong with Perl, and why Python.
&nbsp;
To read this program, you might need the documents of python:
http://docs.python.org/index.html
&nbsp;
You can also find older version here:
http://www.python.org/doc/versions/
&nbsp;
To learn Python, you can browse my tutorials:
http://ez2learn.com/
&nbsp;
If you got any problem about this program, feel free to ask.
&nbsp;
Author: Victor Lin (bornstub@gmail.com)
        http://blog.ez2learn.com
&nbsp;
2009/4/27 - Create first version
2009/4/30 - Fix the problem of keep-alive (fore the connection closed)
&nbsp;
&quot;&quot;&quot;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">sys</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">socket</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">urlparse</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">signal</span>
<span style="color: #ff7700;font-weight:bold;">import</span> <span style="color: #dc143c;">datetime</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> listenToPort<span style="color: black;">&#40;</span>port<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Listen to specific port and return socket
&nbsp;
    @param port: port to listen
    @return: socket
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># get name of host</span>
    host = <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostbyname</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># create socket and bind, listen</span>
    s = <span style="color: #dc143c;">socket</span>.<span style="color: #dc143c;">socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_STREAM</span><span style="color: black;">&#41;</span>
    s.<span style="color: black;">bind</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    s.<span style="color: black;">listen</span><span style="color: black;">&#40;</span><span style="color: #ff4500;">5</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> s
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> openConnection<span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Open a connection to remote host
&nbsp;
    @param host: host to connect
    @param port: port to connect
    @return: connection socket
    &quot;&quot;&quot;</span>
    <span style="color: #808080; font-style: italic;"># create socket for connecting remote host</span>
    remote = <span style="color: #dc143c;">socket</span>.<span style="color: #dc143c;">socket</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">socket</span>.<span style="color: black;">AF_INET</span>, <span style="color: #dc143c;">socket</span>.<span style="color: black;">SOCK_STREAM</span><span style="color: black;">&#41;</span>
    ip = <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostbyname</span><span style="color: black;">&#40;</span>host<span style="color: black;">&#41;</span>
    remote.<span style="color: black;">connect</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span>ip, port<span style="color: black;">&#41;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> remote
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> analyzeRequest<span style="color: black;">&#40;</span>client<span style="color: black;">&#41;</span>:
    <span style="color: #483d8b;">&quot;&quot;&quot;Parse http request
&nbsp;
    @param child: file of client socket to read request and parse
    @return: (first line of request for http server, http method, socket to url)
    &quot;&quot;&quot;</span>
    first = client.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># parse first line</span>
    method, url, version = first.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># parse url</span>
    result = <span style="color: #dc143c;">urlparse</span>.<span style="color: #dc143c;">urlparse</span><span style="color: black;">&#40;</span>url<span style="color: black;">&#41;</span>
    host = result<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> result<span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span>.<span style="color: black;">find</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">!</span>= -<span style="color: #ff4500;">1</span>:
        host, port = host.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
        port = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>port<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        port = <span style="color: #ff4500;">80</span>
    url = <span style="color: #dc143c;">urlparse</span>.<span style="color: black;">urlunparse</span><span style="color: black;">&#40;</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">''</span>, <span style="color: #483d8b;">''</span><span style="color: black;">&#41;</span> + result<span style="color: black;">&#91;</span><span style="color: #ff4500;">2</span>:<span style="color: black;">&#93;</span><span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;"># check is there a loop</span>
    <span style="color: #ff7700;font-weight:bold;">if</span> host == <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> <span style="color: #ff7700;font-weight:bold;">or</span> host == <span style="color: #483d8b;">'127.0.0.1'</span> <span style="color: #ff7700;font-weight:bold;">or</span> \
        host.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span> == <span style="color: #483d8b;">'localhost'</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Connection to proxy server ignored.&quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> <span style="color: #008000;">file</span>, <span style="color: #483d8b;">&quot;It's not nice to make me loop on myself!.&quot;</span>
        client.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        <span style="color: #dc143c;">sys</span>.<span style="color: black;">exit</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
    remote = openConnection<span style="color: black;">&#40;</span>host, port<span style="color: black;">&#41;</span>
    <span style="color: #808080; font-style: italic;"># the first line for remote socket</span>
    first = <span style="color: #483d8b;">&quot;%s %s %s&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>method, url, version<span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">return</span> first, method, remote
&nbsp;
<span style="color: #ff7700;font-weight:bold;">def</span> main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>:
    <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #008000;">len</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#41;</span> <span style="color: #66cc66;">&gt;</span> <span style="color: #ff4500;">1</span>:
        proxyPort = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span><span style="color: #dc143c;">sys</span>.<span style="color: black;">argv</span><span style="color: black;">&#91;</span><span style="color: #ff4500;">1</span><span style="color: black;">&#93;</span><span style="color: black;">&#41;</span> 
    <span style="color: #ff7700;font-weight:bold;">else</span>:
        proxyPort = <span style="color: #ff4500;">5364</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">##--- Step 1 : Create Socket ---##</span>
    s = listenToPort<span style="color: black;">&#40;</span>proxyPort<span style="color: black;">&#41;</span>
    ip, port = s.<span style="color: black;">getsockname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
    <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Proxy server running on %s ( %s ) port: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>
        <span style="color: #dc143c;">socket</span>.<span style="color: black;">gethostname</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>, ip, port<span style="color: black;">&#41;</span>
&nbsp;
    <span style="color: #808080; font-style: italic;">##--- Step 2 : Wait for request ---##</span>
    <span style="color: #ff7700;font-weight:bold;">while</span> <span style="color: #ff4500;">1</span>:
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Waiting to be of service ...&quot;</span>
        client, address = s.<span style="color: black;">accept</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        clientFile = client.<span style="color: black;">makefile</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        ip, port = address
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;Connection from %s port: %d&quot;</span> <span style="color: #66cc66;">%</span> <span style="color: black;">&#40;</span>ip, port<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;">##---  Step 3 : Read first line of request and analyze it. ---##</span>
        first, method, remote = analyzeRequest<span style="color: black;">&#40;</span>clientFile<span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;">##---  Step 4 : Send request to remote host ---##</span>
        remoteFile = remote.<span style="color: black;">makefile</span><span style="color: black;">&#40;</span>bufsize=<span style="color: #ff4500;">0</span><span style="color: black;">&#41;</span>
        <span style="color: #808080; font-style: italic;"># write first line to remote server</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, first
        <span style="color: #ff7700;font-weight:bold;">print</span> first
        <span style="color: #808080; font-style: italic;"># force the remote connection closed as finish this request</span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, <span style="color: #483d8b;">'Connection: close'</span>
        <span style="color: #808080; font-style: italic;"># read headers from client</span>
        contentLength = <span style="color: #ff4500;">0</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> clientFile:
            line = line.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> line
            <span style="color: #808080; font-style: italic;"># filter headers that we don't want they passed to server</span>
            match = <span style="color: #008000;">False</span>
            <span style="color: #ff7700;font-weight:bold;">for</span> header <span style="color: #ff7700;font-weight:bold;">in</span> <span style="color: black;">&#91;</span><span style="color: #483d8b;">'connection:'</span>, <span style="color: #483d8b;">'proxy-connection:'</span>, <span style="color: #483d8b;">'keep-alive:'</span><span style="color: black;">&#93;</span>:
                <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span>header<span style="color: black;">&#41;</span>:
                    match = <span style="color: #008000;">True</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> match:
                <span style="color: #ff7700;font-weight:bold;">continue</span>
            <span style="color: #808080; font-style: italic;"># get content length</span>
            <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'content-length:'</span><span style="color: black;">&#41;</span>:
                _, length = line.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
                contentLength = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>length<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, line
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
                <span style="color: #ff7700;font-weight:bold;">break</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> method == <span style="color: #483d8b;">&quot;POST&quot;</span>:            
            <span style="color: #ff7700;font-weight:bold;">if</span> contentLength <span style="color: #66cc66;">!</span>= <span style="color: #ff4500;">0</span>:
                data = clientFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span>contentLength<span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">else</span>:
                data = clientFile.<span style="color: #dc143c;">readline</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot;POST body:&quot;</span>, data
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> remoteFile, data
&nbsp;
        <span style="color: #808080; font-style: italic;">##---  Step 5 : Wait for response and transfer it to requestor. ---##    </span>
        <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #483d8b;">&quot; --- Done sending. Response: &quot;</span>
        <span style="color: #ff7700;font-weight:bold;">print</span>
&nbsp;
        contentLength = <span style="color: #008000;">None</span>
        <span style="color: #ff7700;font-weight:bold;">for</span> line <span style="color: #ff7700;font-weight:bold;">in</span> remoteFile:
            line = line.<span style="color: black;">strip</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> <span style="color: #66cc66;">&gt;&gt;</span> clientFile, line
            <span style="color: #ff7700;font-weight:bold;">if</span> <span style="color: #ff7700;font-weight:bold;">not</span> line:
                <span style="color: #ff7700;font-weight:bold;">break</span>
            <span style="color: #ff7700;font-weight:bold;">print</span> line
            <span style="color: #ff7700;font-weight:bold;">if</span> line.<span style="color: black;">lower</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>.<span style="color: black;">startswith</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">'content-length:'</span><span style="color: black;">&#41;</span>:
                _, length = line.<span style="color: black;">split</span><span style="color: black;">&#40;</span><span style="color: #483d8b;">':'</span><span style="color: black;">&#41;</span>
                contentLength = <span style="color: #008000;">int</span><span style="color: black;">&#40;</span>length<span style="color: black;">&#41;</span>
&nbsp;
        <span style="color: #ff7700;font-weight:bold;">if</span> contentLength <span style="color: #ff7700;font-weight:bold;">is</span> <span style="color: #ff7700;font-weight:bold;">not</span> <span style="color: #008000;">None</span>:
            body = remoteFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span>contentLength<span style="color: black;">&#41;</span>
        <span style="color: #ff7700;font-weight:bold;">else</span>:
            body = remoteFile.<span style="color: black;">read</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
        clientFile.<span style="color: black;">write</span><span style="color: black;">&#40;</span>body<span style="color: black;">&#41;</span>
&nbsp;
        remoteFile.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
        clientFile.<span style="color: black;">close</span><span style="color: black;">&#40;</span><span style="color: black;">&#41;</span>
&nbsp;
<span style="color: #ff7700;font-weight:bold;">if</span> __name__ == <span style="color: #483d8b;">'__main__'</span>:
    main<span style="color: black;">&#40;</span><span style="color: black;">&#41;</span></pre></div></div>

<p></code><br />
可讀性很明顯地Python優於Perl，我在這裡說明為什麼，原因其實很簡單，因為Perl加太多語法和用太多特殊符號在他的語言中，Perl對於正規表示法有語法，對於讀檔有特別的語法，對於向系統下指令有特別的語法，Perl對於這些瑣碎的功能加了太多的語法，使得用Perl寫出來的程式難以被簡單的理解，舉個最顯著的例子，就是他的特別變數，Perl有一系列$開頭的特別變數，在那程式裡就出現了幾次</p>
<blockquote><p>$$<br />
$|<br />
$_</p></blockquote>
<p>請問這三個特別變數在Perl中各代表什麼意思? 除非你真的對Perl很熟，否則答案肯定是我不知道，我得翻手冊，這就是為什麼Perl可讀性較差的原因之一，Perl的可讀性一直是很多人所詬病的，接著我們在裡面看到有一行很有趣的是有註解的，他這樣寫</p>
<blockquote><p>$| = 1;    #Disable buffering</p></blockquote>
<p>如果他不寫註解，我敢打賭沒幾個人能光看那一行知道這是在幹什麼的，因為我不太清楚它要disable buffering的原因，而disable buffering又是指哪個buffer? 網路? STDIO? 而且不那樣做也不會怎樣，所以我在Python版裡沒有照著寫這行，但是我們假設我們也需要在Python裡寫這行，那可能會是怎樣寫，我們假設他是要disable socket的buffering，而且我們假設Python有個函數叫disableBuffering()，所以我們相對應的Python版本就這樣寫</p>
<blockquote><p>disableBuffering()</p></blockquote>
<p>看出差別了嗎? 是的，Perl將這些符號做為特殊用途，加了很多特殊的語法，雖然讓程式較短較好寫，但是很明顯地讓可讀性大大地降低，在沒有查手冊之前根本沒辦法得知這一行到底是在做什麼用的，然而，因為用語法來實現太多功能，某種程度上算是不良的設計，因為他們都能夠用函式或函式庫來取代，而函式庫的取代雖然要寫多一點字，但是可讀性大大提升，光是看到disableBuffering()這樣的函數名稱就能很清楚地明白這一行是在做什麼用的，可讀性的差別就是這些語言的天性，也是判斷程式語言優劣的關鍵之一</p>
<h3>可寫性</h3>
<p>可寫性是指一款程式語言是否很容易撰寫</p>
<p>通常當一款程式語言很囉唆或不直覺時，他的可寫性會比較差，但相對的可讀性可能會比較好，反之亦然，以Perl為例子，如果你對那些符號很熟，你可以打很少的字，就寫出你要的功能，但是那樣犧牲了可讀性，但是其實某些情況下可讀性和可寫性都可以達到一個很不錯的平衡，我認為Python就是這樣的例子，Python因為語法限制性高，加上符號的定義也很簡短，所以寫Python的速度很快</p>
<h3>可靠性</h3>
<p>可靠性是指不易讓使用者犯錯，而犯錯也可以很容易的找出來</p>
<p>這比起可讀性和可寫性較難以解釋，但是我想這樣說，如果你受傷不會覺得痛，會發生什麼事? 答案很簡單，很快的你就會上西天，人類的痛覺是一種可以自我警告的系統，而程式的可靠性，所指的犯錯容易找出來也就是這個意思，試想一下，當你不小心打錯了程式，但是因為程式語言語法設計上很寬鬆，編譯一樣可以通過，他沒有警告你錯誤，程式可以執行，但是卻不是正確地執行，很明顯的後果就是開發者沒辦法輕易的得知這個問題，更糟的是因為沒有辦法偵測出錯誤，錯誤一樣還在那裡，如果你開發的是飛機的飛航系統，很快的你的程式在開發期間沒有讓你知道有問題，當真正運行時問題才暴發開來，這時麻煩就大了，這就是為什麼可靠性很重要的原因，舉個C語言的實例</p>
<pre lang="c++">int array[10];
int i = 13;
array[i] = 5; // oops</pre>
<p>請問上面這段程式碼會有什麼樣的結果呢? 首先，這樣寫語法正確，所以可以執行，而C語言為了效能考量並不會對陣列索引的邊界做檢查，所以當你的程式跑到最後一行，對一個超出你陣列範圍的整數做指派會發生什麼事? 答案是不知道，很簡單的原因是，這array是放在stack裡的，你今天對他做存取，它會從它在stack中分配到的空間位置往下加元素個數乘上索引的大小，因為他不做檢查，所以只是忠實地去做，所以要看在stack中那個位置到底是什麼，那個倒霉鬼可能是呼叫函數的位址，可能是某人分配的區域變數，端看當時的環境是怎樣，被蓋掉的那塊記憶體的用途不同，發生的事情也會不一樣，這個叫做行為未定義，你永遠沒辦法確切的說出會發生什麼事，就像你拿一塊石頭從101往下丟一樣，會不會砸到人、砸到誰根本都是無法預知的事情，這整個程式碼所要呈現的重點就在於，因為為了效率考量，不做檢查，所以出錯也沒辦法知道，C語言就是這樣自由的語言，因為這樣的特性使它在低階的應用上受到歡迎，但是也因為這樣，很多新手程式設計師難以駕禦C/C++就是這個原因，因為C/C++太自由了，他們常常會怎麼死的都不知道</p>
<p>因此，做為一款嚴僅的程式語言，最好要能盡早在程式的編譯時期，就讓使用者知道出錯了，語法錯誤的檢查某些程度上來說是這樣的用意，C++ meta-programming的觀念裡，也有一條讓錯誤盡早在編譯時期被發現，與其等程式執行了才出錯，在編譯時期就發現才是比較好的，因為程式執行的不確定性比較多</p>
<h3>可攜性</h3>
<p>可攜性是指一個程式語言對於環境的依賴性有多低</p>
<p>我們都習慣使用Windows作業系統，但是事實上世界上還有很多種不同的電腦作業的環境，程式是要在這些環境中執行的，一個可攜性好的程式語言應該要和平台沒有關聯，或是做適當的介面來降低藕合度，舉個例子，你如果用VB6.0寫一個視窗程式，那麼他可以在Linux下面跑嗎? 就我所知的答案應該是不行，而相對於Python，Python的語言基本上是和平台無關的，如果搭配一個一樣可攜性很好的視窗函式庫就能寫出跨平台的視窗程式，能在Windows下跑，也能在Linux跑，所以相較之下Python的可攜性就比VB6.0來得好很多，大多數常見的程式語言可攜性其實都很不錯，從C/C++、Java、Perl、Python等都能在各大平台看到這些語言的身影，但是也是有某種程度上的差別，有些語言雖然有可攜性，但並不是完全地可攜，C/C++就是很好的例子，同樣一隻程式，在不同的環境下，很多時候你可能得視你編譯的環境、平台來對程式做某種程度上的修改，才能在其它平台執行，因為他是屬於靜態的語言，所以沒有辦法，靜態語言的可攜性基本上會比動態語言差</p>
<h2>主觀的評估條件</h2>
<p>上面提到的那些是客觀的評估條件，照程式語言裡的話，其實還少了成本和一些瑣碎的部份，但因為太囉唆就不在這裡多提，接著要介紹的就是主觀的程式語言好壞的評估條件，基本上我所學的程式語言課程沒有提到這部份，是我自己加上來的，因為我覺得這是很重要的一個部份，在評估完上面這些項目後，要來看的就是主觀的評估項目</p>
<h3>語言哲學</h3>
<p>我所能想到最主要也最重要的主觀評估條件就是語言背後的哲學，很多語言設計都有思想的，不是高興隨便亂設計的，他們很多都是從這些中心思想出發來進行設計，當遇到設計上的兩難問題時，他們會以這些中心思想來做為發想，並不是每款程式語言都有顯著的哲學口號，或許是我不知道，我在想brainfuck的哲學思想是"Fuck your brain"嗎?</p>
<p>但是有一些語言的中心思想很明確，而且他們也都照著這個中心思想在發展，有趣的是有兩個完全相反的中心思想，剛好是做為語言設計的哲學例子，那就是Perl和Python，首先來看Perl的哲學:</p>
<blockquote><p><a href="http://en.wikipedia.org/wiki/There%27s_more_than_one_way_to_do_it">There&#8217;s more than one way to do it</a></p></blockquote>
<p>他的想法就是，可以有很多種方法可以辦到同樣的事情，而Zen of Python，也就是Python的禪道剛好相反</p>
<blockquote><p>There should be one&#8211; and preferably only one &#8211;obvious way to do it.</p></blockquote>
<p>我對於Perl的思想不瞭解，我不太明白他們那樣想的理由是什麼，但是我很清楚Python他所想表達的，相較於Perl，因為同一件事情可以有很多方法達成的話，那麼通常依照人的性格，一百個人可能就會寫出一百種不同的程式，而且在這些程式中有大部份都是濫用的程式，程式碼也因為可能性太多，會難以理解，但是以相反的哲學來設計的話，只有一個明確的方法，那麼就直接使用吧，一來不需要花額外的時間浪費在思考非解決問題的關鍵上，接著也因為只有一個明顯的方法來達成，可讀性自然也較佳，因為顯而易見，這是我對Python禪到的見解，但是佛曰: 不可說，即然他名為禪我想意思就是要你自己悟，這就是一個程式語言背後哲學有趣的地方</p>
<p>然而，上面Python提到的這句話，並不是Python禪道的全部，而是做為中心思想很重要的一句，事實上<a href="http://www.python.org/dev/peps/pep-0020/">Python的禪</a>是由好幾句組成的:</p>
<blockquote><p>Beautiful is better than ugly.<br />
Explicit is better than implicit.<br />
Simple is better than complex.<br />
Complex is better than complicated.<br />
Flat is better than nested.<br />
Sparse is better than dense.<br />
Readability counts.<br />
Special cases aren&#8217;t special enough to break the rules.<br />
Although practicality beats purity.<br />
Errors should never pass silently.<br />
Unless explicitly silenced.<br />
In the face of ambiguity, refuse the temptation to guess.<br />
There should be one&#8211; and preferably only one &#8211;obvious way to do it.<br />
Although that way may not be obvious at first unless you&#8217;re Dutch.<br />
Now is better than never.<br />
Although never is often better than *right* now.<br />
If the implementation is hard to explain, it&#8217;s a bad idea.<br />
If the implementation is easy to explain, it may be a good idea.<br />
Namespaces are one honking great idea &#8212; let&#8217;s do more of those!</p></blockquote>
<p>這麼多的句子，以我快十年寫程式的經驗，我都能很認同這些話所說的，不過有些我還是不太明白，像是Simple is better than complex.就顯而易見的是KISS原則，而後面的Complex is better than complicated.就不太瞭解他所表答的意思</p>
<p>做為一款優秀的語言，Python有他精深的哲學做為發展的中心思想，而這思想也深得我心，所以我喜歡Python，Python的所做所為都能體現出他寫的這些，每個人認同的哲學可能會不太一樣，而做為認同的這部份，就是較為主觀的評估條件，做為程式語言的哲學，上面那些客觀層面討論完之後，剩下的就是這些思想，而思想就很難分對錯，這也是為什麼程式語言討論好壞最後都變成無止盡的爭論，因為他們的中心思想不一樣</p>
<h2>結論</h2>
<p>寫了這麼多，就是希望大家能夠瞭解程式語言要怎樣比較，不是說程式語言沒有好壞之分來當做不知道怎麼評估的藉口，又或著只會單靠喜好來決定程式語言</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.ez2learn.com/2010/01/08/how-to-compare-languages/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>
