<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    bt下載與小說520

    bt下載與小說520

      BlogJava :: 首頁 :: 新隨筆 :: 聯系 :: 聚合  :: 管理 ::
      16 隨筆 :: 0 文章 :: 6 評論 :: 0 Trackbacks

    2008年10月5日 #

    Mozilla Public License

    MPL License,允許免費重發布、免費修改,但要求修改后的代碼版權歸軟件的發起者。這種授權維護了商業軟件的利益,,它要求基于這種軟件得修改無償貢獻版權給該軟件。這樣,圍繞該軟件得所有代碼得版權都集中在發起開發人得手中。但MPL是允許修改,無償使用得。MPL軟件對鏈接沒有要求。

    SD開源協議

    BSD開源協議是一個給于使用者很大自由的協議。可以自由的使用,修改源代碼,也可以將修改后的代碼作為開源或者專有軟件再發布。 當你發布使用了BSD協議的代碼,或則以BSD協議代碼為基礎做二次開發自己的產品時,需要滿足三個條件:

    1. 如果再發布的產品中包含源代碼,則在源代碼中必須帶有原來代碼中的BSD協議。

    2. 如果再發布的只是二進制類庫/軟件,則需要在類庫/軟件的文檔和版權聲明中包含原來代碼中的BSD協議。

    3. 不可以用開源代碼的作者/機構名字和原來產品的名字做市場推廣。

    BSD代碼鼓勵代碼共享,但需要尊重代碼作者的著作權。BSD由于允許使用者修改和重新發布代碼,也允許使用或在BSD代碼上開發商業軟件發布和銷售,因此是對商業集成很友好的協議。而很多的公司企業在選用開源產品的時候都首選BSD協議,因為可以完全控制這些第三方的代碼,在必要的時候可以修改或者二次開發。

    Apache Licence 2.0

    Apache Licence是著名的非盈利開源組織Apache采用的協議。該協議和BSD類似,同樣鼓勵代碼共享和尊重原作者的著作權,同樣允許代碼修改,再發布(作為開源或商業軟件)。需要滿足的條件:

    1. 需要給代碼的用戶一份Apache Licence

    2. 如果你修改了代碼,需要再被修改的文件中說明。

    3. 在延伸的代碼中(修改和有源代碼衍生的代碼中)需要帶有原來代碼中的協議,商標,專利聲明和其他原來作者規定需要包含的說明。

    4. 如果再發布的產品中包含一個Notice文件,則在Notice文件中需要帶有Apache Licence。你可以在Notice中增加自己的許可,但不可以表現為對Apache Licence構成更改。

    Apache Licence也是對商業應用友好的許可。使用者也可以在需要的時候修改代碼來滿足需要并作為開源或商業產品發布/銷售。

    GPL

    GPL許可證是自由軟件的應用最廣泛的軟件許可證,人們可以修改程式的一個或幾個副本或程式的任何部分,以此形成基於這些程式的衍生作品。必須在修改過的檔案中附有明顯的說明:您修改了此一檔案及任何修改的日期。 您必須讓您發布或出版的作品,包括本程式的全部或一部分,或內含本程式的全部或部分所衍生的作品,允許第三方在此許可證條款下使用,并且不得因為此項授權行為而收費。

    LGPL

    Linux就是采用了GPL。GPL協議和BSD, Apache Licence等鼓勵代碼重用的許可很不一樣。GPL的出發點是代碼的開源/免費使用和引用/修改/衍生代碼的開源/免費使用,但不允許修改后和衍生的代碼做為閉源的商業軟件發布和銷售。這也就是為什么我們能用免費的各種linux,包括商業公司的linux和linux上各種各樣的由個人,組織,以及商業軟件公司開發的免費軟件了。

    GPL協議的主要內容是只要在一個軟件中使用(“使用”指類庫引用,修改后的代碼或者衍生代碼)GPL協議的產品,則該軟件產品必須也采用GPL協議,既必須也是開源和免費。這就是所謂的”傳染性”。GPL協議的產品作為一個單獨的產品使用沒有任何問題,還可以享受免費的優勢。

    由于GPL嚴格要求使用了GPL類庫的軟件產品必須使用GPL協議,對于使用GPL協議的開源代碼,商業軟件或者對代碼有保密要求的部門就不適合集成/采用作為類庫和二次開發的基礎。

    其它細節如再發布的時候需要伴隨GPL協議等和BSD/Apache等類似。

    Public Domain

    公共域授權。將軟件授權為公共域,這些軟件包沒有授權協議,任何人都可以隨意使用它。

    Artistic許可

    使作者保持對進一步開發的控制。

    posted @ 2008-12-18 13:55 bt下載| 編輯 收藏

    著第3屆bt論壇的順利結束的秋風,我也來分享一下自己在前端優化方面的一些些小經驗,其實這些經驗本身都是來自yahoo的優化原則,不過經過ahuaxuan自身的實踐和再次的思考,把原來的原則都進行了分組和分析.不過由于ahuaxuan bt涉及到的東西有限,并沒有經歷過全部的優化點,所以只把自己做過的拿出來和大家討論討論,其中不免加入自己一些觀點,希望大家指正.

    先說說目標,前端優化的目標是什么,一個字:快.兩個字:更快.那么下面我們來看看慢的網頁將會給我們帶來什么:
    1. 慢的頁面可能會網站失去更多的用戶.

    2. 慢500ms意味著20%的用戶將放棄訪問(google)

    3. 慢100ms意味著1%的用戶將放棄交易(amazon)

    4. 慢 ???ms意味著??%的用戶將放棄xx(your site)

    所以我們的目標很明確,就是要網頁展現的速度更快.
    經過ahuaxuan的實踐和總結,其實要讓網頁展現更快只需要注意幾個大的方面,下面會一一描述這幾個大的方面.


    [size=medium]1減少http請求,我把它排在了第一點,為啥要在第一點呢,很簡單,因為它最重要.



    如何做呢.讓ahuaxuan帶著大家分析一下這個問題.從何處著手呢.ahuaxuan大聲疾呼,我們要從數據開始.ok,一般來說,我們從變化性上把數據分成兩種類型,變和不變.那么不變的數據可以緩存,變化的數據不能緩存,這是一個常識,也就是說要減少我們的http請求次數這個目標可以轉換成把數據分為變化和不變化兩個部分.不變化的數據不需要再次請求,這樣http請求的次數就減少了,下面我們分點來描述將數據分類的途徑.


    1. 合并腳本文件
    包括腳本,樣式和圖片,可以有選擇的把一些Js和css可以合并成一個文件,一些圖片可以使用css sprites技術.這樣做的原因是什么?做過web開發的人都知道,js和css基本是不變的,是靜態文件,圖片亦然.那么不變的文件如果適當的合并在一起,會有什么效果呢?請求的次數從多次變成了一次.這樣http請求的次數就減少了.當時合并之后,文件體積變大了,會影響速度嗎?答:肯定會啊,不過這里是需要權衡的,比如我100份靜態文件,合并成10份還是合并成1份這就得看你得具體情況了.

    2. 指定Expires或者Cache-Control,
    對于靜態內容:設置文件頭過期時間Expires的值為“Never expire”(永不過期)
    動態頁面,在代碼中添加cache-control,表示多少時間之后過期,如:
    response.setHeader("Cache-Control", "max-age=3600");
    如果使用了Expires文件頭,當頁面內容改變時就必須改變內容的文件名。通常是在文件內容后加版本號
    這一點是大多數人都忽略得,之前很多人在壇子上發布自己得小系統,還有demo,ahuaxuan跑過去一看,my god,一堆又一堆得js,css,既沒有恰當得合并,也沒有設置過期時間.每次刷新頁面都要重新下載這一堆又一堆的js,css.http請求那叫一個多啊.無謂了流量就這樣產生了.

    這一點在企業應用的系統中也時有發生.比如我們使用extjs作為前端的技術,400多k啊,每打開一個頁面都導入,下載這個js,夠無聊的.那么童子們可能就要問了,靜態文件為啥不用apache,lighttpd等呢,答,用了又怎么樣,不設expire或者max-age不是一樣要下載,最好的方法是寫一個filter,再filter中判斷,如果url滿足一定的條件(比如符合配置文件中的正則表達式),那么就設置一個max-age,這樣就ok,太簡單了,幾行代碼就可以搞定.快哉.

    3. 緩存Ajax請求
    緩存的方法同動態頁面,ajax請求需要使用get方式,url長度為2k(ie)限制(post請求有兩個過程,1發送請求headers,2發送請求數據,根據http規范,get請求只會發送一個tcp包).--------這一段話來自yahoo,先不管其真假,我們從另外一個方面來考慮一下為什么最好使用get方式,講一個ahuaxuan經歷過的事情,之前有一個項目的ajax請求使用了post方式,后來發現經常出錯,而且拋出了squid的錯誤,因為我們的網站使用了squid,問題就出在這里了,從http協議上可以了解到,method=post是指把數據提交到服務器上去,那么squid的一個特性是不會緩存post請求(事實上它確實不應該緩存,因為這樣會違反http協議中的語義),把ajax請求改成get方式之后,一切恢復如常.

    4. 移除重復的js
    重復的js導入也有可能導致ie重新加載該腳本.沒啥好說的,照做.

    5. 避免重定向
    有一種經常被網頁開發者忽略卻往往十分浪費響應時間的跳轉現象。這種現象發生在當URL本該有斜杠(/)卻被忽略掉時。這時候會返回一個301的狀態碼,然后瀏覽器重新發起一次請求.在企業應用里,重定向是我們在企業應用中常用的技術,不過用在網站項目上,您可要小心了,因為普通的重定向其實是server在response header中設置http status=302,瀏覽器收到之后,判斷出是302,會重新發送一個請求,目標地址是前一次返回中指定的地址.在網站項目中如果可以不用重定向就別用吧.如果您做企業應用項目,ok,關系不大,您就放心的”定”吧.

    小節,ahuaxuan把減少http請求次數分為了以上5個小點,每個小點之后附加一些實例,大家可以根據這些點來判斷自己的項目是否可以有優化的地方.


    使用cdn
    讓內容更靠近用戶,這有啥好說呢,原理很簡單,就是根據用戶瀏覽器所在機器的ip來判斷哪些服務器離用戶最近,瀏覽器會再次去請求這些最近的機器.一般的cdn服務商是通過開發自己的dns server來達到這個目的的.不過這個是通常情況哦,技術實力比較高,或者場景比較特殊的公司會開發自己的cdn.當然不管怎么說,使用cdn肯定可以使頁面響應更快(也包括音頻,視頻,圖片,文本文件,等等等等)

    減小返回數據的體積
    1. 使用gzip壓縮返回數據
    Gzip壓縮所有可能的文件類型是減少文件體積增加用戶體驗的簡單方法。比如本來400k的文件,壓縮一下之后只有50k-100k,那么網絡的流量就立刻下來了,壓縮的代價是服務器端要壓縮文件,需要消耗cpu,瀏覽器需要解壓文件,也需要消耗cpu,不過對于現代這么nb的pc,來說,瀏覽器解壓一下數據帶來的cpu消耗簡直不值一提.所以您就壓吧.不過壓的時候要小心哦,有的瀏覽器在特定場景下會出去一些小bug,導致頁面不正常.比如ie6在跨域的時候可能會有些小麻煩,把這部分數據的gzip去掉就可以了.

    2. 最小化js文件和css文件
    壓縮js可以使用JSMin或者YUI Compressor,后者同時可以壓縮css,這個也沒啥好說的,照做吧.

    3. 將css和js獨立成外部文件
    其實這一點也可以看成是區分不變數據和變化數據.很多人喜歡在頁面商寫很多很多的js和css,這些數據其實都是不會變化的數據,也就是說這些數據也是可以緩存在瀏覽器上的,通過把它們獨立成外部文件,可以把這些數據緩存起來.這樣做看上去是增加的請求的次數,但是由于第一次請求之后該部分數據已經被緩存,所以第二次就無需再請求后端,減少了網絡帶寬的開銷.

    優化Cookie

    1. 減小cookie體積
    能不放就別放吧,為啥呀,cookie就象鑰匙串,只有出門和回家得時候才用,但是一整天你都要帶在身上,麻煩不.
    2. 合理設置Cookie域
    由于二級域名可以拿到一級域名得cookie,那么如果,而二級域名之間確不能相互共享cookie,所以合理得設置cookie得域名也可以避免無必要得帶寬浪費和響應速度得增加.
    3. 設置合理的cookie過期時間
    該過期就過期,不要讓不必要的數據一直帶在身上走來走去.
    4. 使用域分離
    為圖片或者其他靜態資源文件使用子域或者建立新的獨立域名(申請新的域名),避免無必要的cookie傳輸,當然也是要在有必要得情況下,圖片類網站肯定有必要,javaeye上得圖片并沒有使用域分離,所以我們得cookie其實會帶到壇子得圖片服務器上去,每次請求圖片都是如此(不過還好,壇子里沒有什么圖片,所以這方面的浪費不大).

    小結,其實cookie上得問題,單詞請求看上去也不是什么大問題,好像是無所謂得事情,就那么幾十個byte,至于嗎,不過大家都聽說過水滴石穿,繩鋸木斷的故事.所以該做的,我們還是要做,正所謂,勿以善小而不為,勿以惡小而為之.
    優化瀏覽器加載
    1. 將css放在頁面頂部加載
    把樣式表放在文檔底部的問題是在包括Internet Explorer在內的很多瀏覽器中這會中止內容的有序呈現。瀏覽器中止呈現是為了避免樣式改變引起的頁面元素重繪。用戶不得不面對一個空白頁面。
          HTML規范清 楚指出樣式表要放包含在頁面的<head />區域內:“和<a />不同,<link />只能出現在文檔的<head />區域內,盡管它可以多次使用它”。無論是引起白屏還是出現沒有樣式化的內容都不值得去嘗試。最好的方案就是按照HTML規范在文 檔<head />內加載你的樣式表。

    2. 將js放在頁面底部加載
    腳本帶來的問題就是它阻止了頁面的平行下載。HTTP/1.1 規范建議,瀏覽器每個主機名的并行下載內容不超過兩個。如果你的圖片放在多個主機名上,你可以在每個并行下載中同時下載2個以上的文件。但是當下載腳本時,瀏覽器就不會同時下載其它文件了,即便是主機名不相同。

    Js放在底部加載其實并不影響瀏覽器展示頁面,除非用戶會在js加載完成之前就調用某個js方法,比如說頁面剛展現到一半,但是恰好這一半里有一部分是調用了還未下載的js,這個時候就會出問題了,如果童子們遇到這種情況,可以把這部分js先加載.

        
    總結一下下:以上這些優化點其實只是前端優化的部分內容,不過根據80/20原則,這些優化點已經覆蓋了80%的情況了,同時前端優化其實也不是什么復雜的東西,原理上是很簡單的,更多的是需要我們的實踐,因為我們可能會碰到各種各樣的問題,而很多的這些問題其實一般是預測不到的.只有遇到過才知道.
    說的不對的地方請大家拍磚,或者童子們也可以把自己的經驗在這里和大家分享一下.代表其他童子表示十分的感謝.

    當然,由于ahuaxuan水平有限,文章中難免有不到之處,還望不吝指正,謝謝.
    posted @ 2008-12-04 20:31 bt下載 閱讀(1547) | 評論 (3)編輯 收藏

    企業向國家工商總局申請對百度濫用市場支配地位進行反壟斷調查,并處1.7億元罰款 bt吧。

      本報記者 韋文潔

      目前,國內對百度的競價排名雖然詬病頗多,但在制約手段的建立上處于真空狀態,缺乏相應的措施。在業界評論家看來,如果國內搜索控制輿論沒有相關的法律法規來制裁,總有一天,網絡自由也將會淪為資本的附屬品 色即是空

      2008年的這個秋天,對北京百度網訊科技有限公司(以下簡稱百度)來說,可謂多事之秋。

      10月31日,就在秋末的最后這幾天,受河北唐山人人信息服務有限公司法定代表人王冠玨的委托,北京市邦道律師事務所李長青律師,把一冊厚達91頁16開本的《反壟斷調查申請書》,送到了國家工商總局反壟斷處一位官員手中,申請對百度濫用市場支配地位的反壟斷調查。據這位官員告訴他,這是反壟斷法實施以來,發生在網絡領域的第一例。

      而在此之前,9月8日,淘寶網“為杜絕不良商家欺詐”,首次向外界宣布屏蔽百度搜索鏈接,向其公正性公開提出抗議;9月12日,百度因被披露涉嫌收取300萬元保護費屏蔽三鹿奶粉負面新聞,被卷入震驚全國的“三鹿問題奶粉”事件之中,成為公眾口誅筆伐的對象。

      更早一些,在今年的秋初,因質疑“競價排名”的貓膩,百度就被深圳律師黃維領告上法院,如果不是百度提出管轄權異議,此案恐怕已在深圳市福田區人民法院開庭審理。

      “發難”一場連接一場,面對來自南北的不斷夾擊,百度這個“全球最大的中文搜索引擎”,如何將這股訴訟潮化險為夷,巧渡搜索引擎行業所面臨的經營模式之困,化解新技術帶來的法律難題,成為業界關注的焦點。

      異常變化

      2007年初,曾有10年經營藥品生意的唐山人王冠玨,在工商局登記注冊了唐山人人信息服務有限公司,創辦了一個普及醫藥知識及招商的網站———全民醫藥網。

      為了提高網站的點擊率,增加客流量,全民醫藥網和百度河北代理商簽了一個《競價排名協議》。

      所謂“競價排名”,就是搜索引擎商推出的一種業務。當用戶搜索一些常用詞語時,從搜索引擎服務商購買了服務的廠商的名字就會排在搜索的前列。每當用戶點擊搜索的結果進入廠商的主頁時,廠商就要向搜索引擎服務商繳納一次費用,也就是搜索引擎的廣告收入。

      全民醫藥網和百度簽訂的這個競價排名,參與時間為2008年3月至9月份,金額8.9萬元,排位于第3名,點擊一次最低價格為0.55元,最高為3.8元。

      參與競價的最初幾個月,是全民醫藥網和百度的蜜月期。全民醫藥網做的全國廠家招商、招會員,在百度搜索排第一名。他們網站的客流,高峰時日瀏覽量達8000次,每月固定客戶以1000人的比例上漲。

      誰知前景開始看好的時候,因為全民醫藥網要改版,6月至8月,全民醫藥網把競價支付價格調到最低時,異常便開始出現了。

      7月5日一上班,商務部經理李娟就慌慌張張地跑來告訴王冠玨,“今天在百度里輸入全民醫藥網的網址,鏈接一下子突然少了,以前的八萬多條信息,只剩下了一個頁面4條記錄”。

      身為商人的王冠玨深知,訪問量就是網站的生命,新客戶來不了,老客戶不會來,做免費的廣告,商家也不會干。從百度來的訪問量一直占全民醫藥網90%的客流量,如果不及時改變這種異常變化,全民醫藥網只能是“坐以待斃。”

      為了解決面臨的“滅頂之災”,作為百度的一個客戶,王冠玨趕緊讓技術部長王運嶺,給百度總部和百度石家莊代理商發信和去電,反映這一異常變化。但百度的電話始終打不通。最后好不容易收到了石家莊百度的回信:“通常這種變化是正常的,是完全自動的,并不表示會對個別網站進行懲罰。”

      可是,讓王冠玨焦慮不已的是,到了7月10日,全民醫藥網的日訪問量驟減,從前一日的2961IP驟減為701IP。而后來以2008年7月10日為分界點的前后兩個月對比,全民醫藥網的月訪問量從前一個月的88095IP銳減至18340IP,日均訪問量從2936IP銳減至611IP,會員已經在網上搜不到全民醫藥網,網站幾乎沒人來光顧了。再和百度聯系,一點音信都沒有。

      7月14日,焦慮不已的王冠玨不得不再次給百度去信哀求:“就算是你們客服說的是因為系統自動更新,但更新也不能差距這么大呀?現在幾乎就在百度里找不到帶著全民醫藥網域名的內容了……請幫我們查出原因,速回郵件或致電。”

      但直到現在,他也沒有等來百度的郵件或回電。

      “降權懲罰”

      9月初,王冠玨給全民醫藥網換了一個域名,希望百度能夠收錄他們網站,但是一個月過去了,一條記錄都沒有。

      2008年9月25日,王冠玨在查詢谷歌、雅虎對全民醫藥網的收錄情況時,結果分別顯示為6690條及3000多條,而其他的包括有道、搜狗,都比百度多。

      面對這種異常,王冠玨真是百思不解。經過走訪大量的網站,咨詢行內專家,翻閱大量資料后,發現他們也遭遇過類似的結果。

      一些站長告訴他,之前在百度做了競價排名,如果后來不做,很容易就被百度屏蔽了。比如:重慶某知名民營醫院在建立自己的網站后,在百度、谷歌、雅虎等搜索引擎上搜索排名一直排第一。但是,從今年8月開始,用百度竟然再也搜索不到醫院網站了,但用谷歌、雅虎卻能夠搜索到,而且還是排位第一。這讓醫院感到十分疑惑,便以各種方式向百度反映這一情況,但都未得到令人信服的答復。迫于無奈,醫院負責人趕緊投錢參加百度的競價排名,很快,醫院的網站又“神奇地”在百度上出現了。

      2005年10月至2006年4月,365數碼網曾在百度做競價排名廣告。而當他們停止續費,不再在百度上投放廣告后,竟然被百度“屏蔽”。

      據中搜網的技術專家介紹,所有的搜索結果都可以進行人工干預,所謂屏蔽就是在搜索程序中嵌入針對特定信息的“黑名單”,從而使機器自動不去抓取指定域名的網頁,從而實現自己的營銷目的。

      王冠玨的一位網友還告訴他,其代理的客戶大部分在行業中有較強的影響,網站也都具有相當的流量。在購買百度關鍵詞競價之前,在百度搜索頁左邊的排序中,基本都能排在前幾名,而在購買了百度的關鍵詞競價服務后,反而在首頁很難找到。

      “顯然,百度在非付費的自然排序中有意下降客戶的排名,目的就是希望這些客戶對于關鍵詞競價這種付費服務產生依賴。”王冠玨的網友說。

      因此,早在2005年,一些網站站長甚至結成了“反百度聯盟”,并且獲得了信息產業部備案序號(豫ICP備05009507)。據《瞭望》報道,聯盟的發起人郭振東,2004年發現自己創辦的文學網站美人魚社區被百度屏蔽。此后,他在與百度上海公司員工的接觸中獲悉,只要交6000元就能將被封的網站解禁,并承諾在一年內不再屏蔽。因此,他認為百度之所以對網站進行屏蔽,是為了推廣百度的競價排名服務,遂發起“反百度聯盟”,收集百度公司對待站長和網友不公正的證據。

      “沒在百度做競價排名廣告前,還可以在百度上搜索到365數碼網,現在卻搜不到了。早知道這樣,還不如一開始就不做呢。”該365數碼網負責人認為,百度“封殺”365數碼網的目的,在于迫使其繼續交錢給百度做競價排名廣告。

      “最令人不服氣的是,用什么評定中小網站該不該被屏蔽,這一系列的標準都是百度自己在操作,外人無法知道,更無法考證和干涉。”一位網友告訴王冠玨。

      看一看他人,比一比自己,王冠玨徹底明白了,因為自己的網站開始有了4000以上的客流量,它一看你的IP這么高,開始能賺到錢,為什么還不到我這里來交錢?便給你的網站來了個“降權懲罰。”

      但百度企業市場部總監舒迅曾對“屏蔽”一說斷然否認:“百度搜索引擎上是否收錄一個網站,與這個網站是否參與百度競價排名推廣沒有任何關系。百度收錄的中文網站數是全球最多的,但并不承諾收錄每一個網站。”

    百度壟斷

      “百度一下”,幾乎已經成為廣大網民最為常見的習慣性搜索。

      自7月份以來,不斷有客戶問王冠玨:“在網上為什么搜不到你們網站?”網民一般都使用百度,他們認為在百度搜不到,就是在網上搜不到。

      李長青律師認為,百度的屏蔽行為對其他網站之所以構成封殺是基于其獲得的市場支配地位。

      據相關資料表明,2008年第2季度,百度占據中國搜索引擎市場份額的64.4%。第3季度,坐擁中國搜索市場近2/3份額。到今年10月23日,百度網站發布公司新聞,已經在中國搜索引擎市場穩穩占據70%以上市場份額。雖然它不過是一個工具,但它現在形成了一個霸主的地位。將對手遠遠拋在后面。

      《反壟斷法》第19條第一款第一項規定,有下列情形之一的,可以推定經營者具有市場支配地位:一個經營者在相關市場的市場份額達到二分之一的。上述資料表明,百度已經完全獲得了中國搜索引擎市場的支配地位。

      正是因為百度具有了這樣的市場地位,其屏蔽行為才具有了封殺其他網站的能量和效果。百度也利用此舉,贏得了巨大的收益:2007年,百度年收入為17.444億元人民幣,比2006年增長108.2%。而其2008年第二季度的財報顯示,收入突破一億美元。

      記者一位在北京經營網站的朋友則認為,對于眾多中小網站來講,其絕大多數的流量都來自于百度搜索引擎這個“入口”。因為絕大多數網民往往只能記住網站的名稱,然后通過搜索到達該網站。因此,擺在眾多網站面前的一個現實問題是,網站流量的訪問入口已經被百度這些大搜索巨頭所壟斷,網站的生殺大權事實上已經被掌握在了別人手中。一旦被搜索引擎“屏蔽”,就很有可能導致網站失去流量。對于搜索引擎“競價排名”的方式,中小網站雖然不滿,但為了生存,大多數都敢怒不敢言。

      現在擺在他們面前的只有兩條路:如果想逃避被百度封殺的厄運,要么屈服于它,參與競價推廣,任其宰割;要么向反壟斷部門舉報,或到法院起訴,通過打官司,尋求公正。

      對王冠玨而言,擺在他面前的這兩條路,沒有一條坦途。

      “生死之戰”

      就在瀕臨絕望的時候,8月1日起施行的《反壟斷法》,讓王冠玨瞬間下定了決心:“我看到了希望。只要法律是公正的,哪怕我失敗,也要去摸這個老虎屁股。否則,你投入再多,由它來主宰,這種狀況永遠也無法改變。”

      10月31日,在送往國家工商總局反壟斷處的《反壟斷調查申請書》中,李長青律師認為,百度對其他網站的封殺,是濫用市場支配地位的行為,造成兩個嚴重的社會后果:其一、百度的封殺行為在實際上消滅了許多網絡經濟中的市場競爭主體,從根本上破壞了公平的市場競爭秩序,嚴重損害了社會主義市場經濟的活力;其二、出于商業目的人工干預搜索結果的行為損害了社會大眾的利益,不符合公眾對于信息公開、客觀的要求。其行為與敲詐勒索無二。這種網絡霸權主義,不僅應該受到道義上的譴責,而且應該受到行政和法律的制裁。

      他建議:執法機構對百度使用的搜索技術規則和搜索過程進行調查;制定搜索技術規范和搜索市場服務規范,強化對搜索引擎服務的管理;責令百度停止其濫用市場支配地位封殺其他網站的違法行為,并處以1.7444億元人民幣的罰款(《中華人民共和國反壟斷法》第47條規定:經營者違反本法規定,濫用市場支配地位的,由反壟斷執法機構責令停止違法行為,沒收違法所得,并處上一年度銷售額百分之一以上百分之十以下的罰款。2007年百度全年營業收入為17.444億人民幣,根據以上規定,可以對其處以1.7444億元人民幣的罰款)。

      中國互聯網協會互聯網政策與資源工作委員會學術專家胡鋼曾對媒體表示,搜索引擎的“推廣方式”或“贊助商鏈接”在本質上依然屬于廣告。但由于嶄新性,搜索引擎尚處在廣告法的監管盲區,這使得搜索引擎服務商得以明目張膽地大打“擦邊球”。

      中國政法大學副教授吳景明則認為,我國《廣告法》第13條早已規定:廣告應當具有可識別性,能夠使消費者辨明其為廣告。而搜索行業的競價排名未能被明確劃歸到廣告范圍,類似搜索引擎這類新技術應用帶來的問題該如何適用法律,目前尚無定論,“這凸顯我國相關立法的滯后”。

      互聯法網總監趙占領也認為:“這類事件反映出我國互聯網領域還存在很多法律空白或爭議之處。比如廣告法和反不正當競爭法如何適用于網絡環境下?搜索引擎運營商在用戶沒有購買競價排名的情況下,不收錄用戶的網站究竟該如何定性?是否屬于強制交易行為?這都需要提供證據來證明搜索引擎運營商此舉的初衷是為了達成交易。”

      目前,國內對百度的競價排名雖然詬病頗多,但在制約手段的建立上處于真空狀態,缺乏相應的措施。在業界評論家看來,如果國內搜索控制輿論沒有相關的法律法規來制裁,總有一天,網絡自由也將會淪為資本的附屬品。

      現在,也許是政府部門著手解決這個問題的最佳時間。10月31日,李長青律師送材料到國家工商總局反壟斷處時,一位官員告訴他:“內部也正在開會,研討這方面的問題呢。”

      在等待行政申請結果的同時,他正忙著收集證據,準備一旦時機成熟,要與百度對簿公堂,展開一場面對面的“生死之戰”。而“一旦這個口子打開了,救活的就不僅僅是全民醫藥網這一家了,而是所有的中小網站和中國的互聯網經濟。”李長青律師說。

    posted @ 2008-11-09 22:08 bt下載 閱讀(229) | 評論 (0)編輯 收藏

    這是 Mashable bt搜集的最新 Web 開發工具箱,包括拖放式 Web 程序創建工具,代碼庫,項目管理,測試程序,以及支持各種編程語言的框架,從 Ajax 到 Ruby 到 Python。這是第二部分。

      參考與資料


    COfundOS - 一個討論開源軟件,尋找投資的平臺。 http://www.5a520.cn
    Mac Yenta - 獨立 Mac 開發者的社會化網絡平臺
    CorkDump - 一個關于常用資源(代碼片段,CSS,Flash 等)討論板。
    All Developers Network - 開發者社會化網絡
    CodePlex - 來自微軟的開源項目托管站點


    UnmatchList - 開發設計者的資源庫
    developerAnalytics - 社會媒體評價與報告,幫助你發現有潛力的社會媒體應用。
    CollabFinder - 一個供開發設計者協同工作的地方。
    測試,監控,Bug 跟蹤,項目管理



    CloudStatus - 對 Web 上最流行云服務進行觀察

    BetaBitz - 一個幫助你尋找 Beta 測試者的地方

    observu - 免費的網站與服務器監測服務

    UserFix - Bug 報告與功能請求站點

    OctaGate SiteTimer - 用來測試你的站點的訪問時延



    Cuzillion - 簡單的頁面測試與檢查程序

    Mob4Hire - 為你的移動應用程序需要大量測試者

    Beanstalk - 一個托管的服務,用來瀏覽跟蹤版本控制,包含對Basecamp 以及 Campfire 等同類服務的集成。

    BUGtrack - 項目管理,Bug 跟蹤

    UserZoom - 用戶體驗測試平臺


    devunity - 曾是一個 Beta 版 Bug 跟蹤服務,現已成為社會化開發平臺
    BuiltWith - 對任何站點提供技術分析與 SEO 信息服務
    fixx - Bug 跟蹤,包含移動設備界面與協同功能
    BugWiki - 一個簡易的 Bug 跟蹤系統
    litmus - 基于 Web 的測試程序,在不同瀏覽器上檢查你的設計


    Bugtagger - 一個包含標簽機制的 Bug 跟蹤程序,方便找到每個 Bug 是與什么相關的
    FEED Validator - 驗證你的 Atom, RSS 以及 KML 聚合服務
    pastebin - Debug 工具允許你協同工作以找到問題所在
    JUnit.org - 一個測試框架,編寫并執行自動測試程序
      Ruby 以及 Ruby on Rails 資源與工具


    Open Source Rails - 一個用來展示基于開源 Ruby on Rails 站點的地方
    Exceptional - Rails 程序異常跟蹤與管理工具
    TuneUp - 使用 Rails 插件檢查你的程序的性能
    heroku - Ruby on Rails平臺,無需安裝配置,直接在瀏覽器中寫代碼。
    RSpec 1.1.8 - Ruby 的開發框架,包括 Scenario 框架與代碼示例框架



    Lovd By Less - 一個開源的 Ruby on Rails 社會網絡平臺
    Merb - 一個 Ruby 框架,包含廣泛功能
    Camping - 一個 Ruby 微框架
      Ajax, Java & JavaScript 資源與工具


    Javxs - 在線工具,將 HTML 轉換為 JavaScript
    frevvo - 一個 Ajax 表單創建工具,包括 XML 支持與拖放式控制
    AjaxDaddy - Ajax 程序演示
    WaveMaker - 可視化,開源 Ajax 所見即所得編輯器
    AppJet - JavaScript 程序編寫平臺



    SproutCore - 一個 JavaScript 框架,用來創建桌面質量的 Web 程序
    Bungee Connect - Ajax Web 程序平臺,跨瀏覽器支持
    Spring - 企業 Java 應用平臺,旨在提高開發效率與程序質量
    jQuery - 一個用于 Ajax Web 開發的 JavaScript 庫。
    KSS - 使用該框架,無需編寫任何代碼就可以開發基于 javaScript 的 UI
        PHP 資源與工具


    Flow3 - 一個最初用于 TYPO3 5.0 的 PHP 框架,但可以獨立使用
    Prado - 一個基于組件的 PHP 5 編程框架,面向對象,事件驅動
      Perl 資源與工具


    Mason - 基于 Perl 的 網站開發引擎,包含 Debug, 模板等工具
      Flash 資源與工具


    OpenLaszlo - 富 Internet 平臺,結合 Flash 與 DHTML,但只需一次編寫
      Python 資源與工具


    GTK+ - 一個用于 Python 的 GUI 開發工具套件
    Wing IDE - 專業的 Python 開發環境,提供30天試用
    Cheetah - 一個開源的,基于 Python 的模板引擎與代碼生成工具

    posted @ 2008-11-06 19:51 bt下載 閱讀(225) | 評論 (0)編輯 收藏

    新聞來源:mashable.com
    這是 Mashable bt搜集的最新 Web 開發工具箱,包括拖放式 Web 程序創建工具,代碼庫,項目管理,測試程序,以及支持各種編程語言的框架,從 Ajax 到 Ruby 到 Python。這是第一部分。

    Web 程序創建類


    DreamFace - 一個用來創建個性化 Web 程序的框架。

    Organic Incentive - 以拖放式界面創建 Web 飾件 http://www.5a520.cn

    dbFLEX - 商務程序開發平臺。

    app2you - 在線創建與定制 Web 程序。

    Qrimp - 一個便宜的數據庫平臺,基于你周圍的數據(如 Excel)創建應用程序。





    Lightspoke - 拖放式程序創建工具,動態過濾,排序,真正的關系數據庫后臺。

    Tersus - 可視化程序創建工具,無需編寫代碼。

    Qt - 跨平臺應用程序框架,可以同時開發應用與界面。


    代碼庫與代碼搜索




    byteMyCode - 代碼搜索

    Snipplr - 幫你存儲,管理所有代碼片段。

    ErrorKey - 錯誤代碼搜索引擎。

    findJAR.com - JAR 文件搜索

    github - 代碼庫,既支持公共代碼,又支持私人代碼,私人代碼通過 SSH 以及 SSL 訪問。



    merobase - 搜索組件。

    Codebase - 代碼庫,技術支持與安裝部署跟蹤程序。

    CONFiles - 配置文件的在線存儲與分享

    CodeSnippets - 公共代碼庫,也支持私人代碼

    GWT-Ext - 免費的,可下載的飾件庫


    開發環境,平臺與框架


    SocialGO - 社會化網絡托管平臺,包括消息,視頻聊天,會員資料,照片分享,博客等
    Pringo - 社會化網絡平臺,功能包括視頻,MP3 支持,圖片庫,圈子,podcasting 等。
    slinkset - 一個用于創建社會化新聞站點的在線平臺
    iWidgets - 社會化 Syndication 平臺,允許你將你的內容聚合到社會化網絡
    WackWall - 一個 Hosted 的社會化網絡平臺




    WhiteLabelDating.com - 一個創建約會,社會網絡,社區站點的平臺,允許以自己公司的名義創建。
    ONEsite - 社會網絡平臺,包括博客,照片與視頻庫,評分與標簽,消息板,私人消息等
    jinity - 免費的社會網絡平臺,包括消息板,聊天,圈子,日志,投票,新聞等
    Magnify.net - 網站視頻工具,包括全套媒體工具
    ShoutEm - 微博客與社會網絡平臺



    Soceeo - 社會網絡平臺,包含文件分享,新聞,投票等
    Swift - 移動站點創建工具,包括多種設計選項,支持 RSS Feed,多媒體等
    SnappVille - 社會網絡平臺,包括組,博客工具,即時消息等
    Ning - 社會網絡平臺,允許使用自己的品牌,包括會員資料,事件列表,甚至 Facebook 集成。
    mixxt - 社會網絡平臺,包括事件,論壇等
    zembly - 一個用來創建社會應用的的平臺,目前處于 Beta 版。Yuku - 一個社區平臺,可定制,擁有很強大的系統管理工具SocialEngine - 基于 PHP 的社會網絡平臺,功能包括 multi-part profiles,子網,搜索友好 URL,博客,圈子等。Cappuccino - 一個用來創建桌面品質 Web 程序的開源框架Jaws - 一個用戶友好 CMS 平臺。   綜合開發工具


    Tabifier - 對你的代碼進行自動縮進。
    Sms2do - 一個用來評測和演示 SMS 程序的免費工具。
    Pretty Printer - 源代碼格式化工具,支持 PHP, JavaScript, CSS 等
    Jitterbit - 一個開源集成方案,提高可擴充性與性能
    Bitizer - 二進制,十進制,16進制,Base 36 以及 ASCII 轉換工具



    thmbnl - 顯示你站點中那些鏈接網頁的縮略圖
    ID Selector - 一個 OpenID 工具
    consoleFISH - 免費的,基于 Web 的 SSH 服務器訪問
    form site - 用來創建自定義表單
    99Polls - 用來創建投票與調查



    Warehouse - 一個非常漂亮的代碼庫瀏覽服務,支持多代碼庫以及非常完善的權限控制
    rendur 2.1 - 一個沙箱程,讓你一邊寫代碼,一邊生成頁面
    Languify - 翻譯管理系統
    ROR Sitemap Generator - 顧名思義,這是一個 ROR 網站地圖生成工具
    MicroMaps - 用來生成交互式地圖,放在你的網站



    Newsfeed Maker - 為你的網站或博客創建 News Feed
    WriteMaps - 網站地圖在線生成工具
    Project Kenai - 免費的開源項目或代碼托管站點
    Launch Splash - 為你還沒有開通的網站免費生成一個歡迎頁面
    Browser Shell - 基于瀏覽器的 SSH 工具
    foigo - 創建自定義表單,調查,以及數據庫AggData - Premade lists for your development projects.SnapCasa - 網站縮略圖工具Versionshelf - 代碼庫安全管理   Mashups 與 APIs


    The Echo Nest - 音樂相關的開發服務 API,包括歌手資料,音樂推薦等功能
    Zeep Mobile - 為你的站點添加基于文本的消息系統
    Clickatell - 一個短消息網關,讓你的網站通過多中連接方式發短消息
    Nonoba - 在線游戲開發 API,支持多玩家。
    Zong - 移動支付平臺,包含開發 API



    Web Shots Pro - 一個 API,開發者可用來在他們的程序中添加網站縮略圖。
    Pushpin - 一個簡單易用的在線地圖 API,支持大量標記以及眾多其它功能
    Datamash - Create widgets and mashups for your site with information anywhere on the Web.借助網絡上的眾多信息為你的站點創建 widgets 與 mashups
    Spicy Pipes - Mashup builder.

    posted @ 2008-11-06 19:50 bt下載 閱讀(257) | 評論 (0)編輯 收藏

    原文作者:miguelcarrasco
    原文鏈接:Who Wants To Beat-Google?
    翻譯:小豬哥

    誰不想打敗Google呢?很宏偉的目標,但怎樣做到呢?每個人對此都有自己的魔幻方法。微軟一度要以440億美元收購Yahoo!,還在R&D投資 bt幾十億,縱然財力如此雄厚,他能做到么?有人認為需要更多的網頁檢索,有人認為應當有更好的界面,這個問題的答案仁者見仁,智者見智。

        而且現在來做這件事情(打敗Google)再合適不過。隨著經濟危機的來臨,大批大批的web 2.0 公司即將破產,那些僅僅依賴互聯網生存的公司也即將倒閉。即便強如Google也在去年受到了沖擊,其股價去年700美元每股,而今跌到286(作者發稿時)。現在看來,互聯網免費的午餐已經消失。

        然而微軟卻一直保持著強勁的勢頭,因為他非常多元化而且在一個領域做得實在太優秀了——軟件!他有著難以想象的money,手中有難以置信的全球智慧人群(接近100,000雇員),同時他還擁有最富有夢想的一些領導者在運籌帷幄。如果有誰能夠做出更好的搜索引擎,那毫無疑問就是微軟。而Google會退縮么,當然也不會。

    社交圖(Social Graph)


    Facebook經常談論的Social Graph著實強大,因此Facebook得以很了解你。他知道你的朋友是誰、你住在哪里、你在哪兒工作……他有圖片、video以及你感興趣的東西。他甚至知道你在哪個社交圈、你想參加什么活動。因而可以說Facebook比你的朋友都了解你。

    搜索怎么了(What’s Wrong With Search Today?)

        當我試著用“GAC”一類的來搜索的時候,返回的結果令我感到荒唐——加拿大抵制協會(Geological Association of Canada)。我是一個軟件開發者,Facebook、Twitter和LinkedIn 都知道這一點,但是Google對此一無所知。所以返回的有效搜索寥寥無幾。我媽媽搜索一個關鍵詞跟我搜索一個關鍵詞得到的返回完全相同。但是我媽媽喜愛 的是手工藝,我喜歡的是軟件開發,我們應該得到不同的結果才對。

        為什么沒有人利用社交圖的數據呢?單純拷貝Google搜索模式、換個Logo是行不通的,人們更換搜索需要理由。在搜索中添加內容才是出路。

        比爾蓋茨在過去的幾年里一而再再而三地提到:搜索的道路還很長。幾個月前我聽到的解決方案——新的界面、一直鼠標滾動的搜索結果(never ending scrolling),這些顯然不是比爾蓋茨想說的。Scrolling endlessly所以你就不用選頁了?這顯然不是解決方式。

        微軟真正應當做到的是:當用Google和Live Search搜索的時候,Live Search返回的結果更好。而且不是好一點,要好很多才行。

    微軟能做什么(So What Can Microsoft Do?)

        毫無疑問,微軟有業內最優秀的開發者、架構師和工程師,同樣也有大筆大筆的錢可以投到搜索中(這一點從他購買Yahoo! 就能夠看出來)。然而微軟要想贏得搜索戰所缺少的東西也很明了:他們需要創意和行動路線,也即“作戰計劃”。Windows, Internet Explorer和Office,微軟當年都不是第一個,但他做出了比其他操作系統更好的操作系統,比其他office套件更好的office套件,比其 他瀏覽器更好的IE,而且他還讓所有這些應用能夠無縫地運行在一起。所以如果微軟擁有戰略,并且能夠正確實施,Live Search將會迅速得到難以想象的市場占有率。

    Live Search 與Facebook關聯(Live Search and Facebook Connect)

        微軟應當充分利用Facebook connect,并將之與Live Search關聯。使用Facebook connect,Facebook用戶能夠在Microsoft Live Search中關聯到他們資料數據和認證證書。通過關聯搜索、結合用戶的資料數據,這個搜索就是“終極搜索引擎”。

    Microformats將是搜索的未來(Microformats are the future of Search)


        Microformats比其他任何瀏覽器都好,以hCalander, hCard和 hReview開始。如果你還從未聽過Microformats,趕緊查查,你就會知道他為什么這么重要。到目前為止,網絡上大部分的數據都是完全無序的。舉個例子你輸入“Contact Miguel Carrasco”搜索,你會搜到我的博客但僅此而已。但你想要找到的是我的聯系卡片。下面是我使用hCalander Microformat來為Winnipeg.net User Group創建一個事件的實例。

       1: <div class="vevent" id="hcalendar-Winnipeg-.net-User-Group-September-Event">
       2:     <a class="url" >
       3:     <abbr class="dtstart" title="2008-09-30T06:00-06:0000">September 30, 2008  6</abbr> –
       4:     <abbr class="dtend" title="2008-09-30T08:00-06:00">8am</abbr> : 
       5:     <span class="summary">Winnipeg .net User Group September Event</span> at
       6:     <span class="location">17th Floor - One Lombard Place - Winnipeg, Manitoba, Canada</span></a>

       7:     <div class="description">What could possibly be better than enjoying some free pizza and pop with your peers while be entertained / educated by a presentation on a single .Net topic? Well, how about an open forum that includes some of the hottest topics in software development to date?! To keep the meeting energized, we will be limiting each topic to 20 minutes, and what's more, each topic will have a subject matter expert on hand to facilitate the session.
       8: 
       9:     Come prepared with questions, project stories, and ideas to one of the most unique user group sessions we have ever had.
      10: 
      11:     Topics will include:
      12: 
      13:     What is BizTalk
      14:     A Real World Silverlight Application
      15:     What is NHibernate
      16:     Why Continuous Integration Is Critical
      17:     Open Forum Free-for-All Session</div><div class="tags">Tags:
      18:     <a rel="tag" >winnipeg</a><a rel="tag" > user group</a><a rel="tag" > .net</a><a rel="tag" > microsoft</a></div>
      19: 
      20: </div>

        一個支持Microformat的搜索引擎可以在搜索結果中得到正確的信息,并且鏈接到網址來為事件注冊

    完美的搜索界面(The Complete Search Interface)

        大家也許都忘記了,Google剛誕生出來的那會,沒有blogs,Video也不大,Facebook和其他社交網絡還在娘胎呢。然而搜索的未來在于內容。人們每月花費成百上千個鐘頭在社交網絡、新網址和博客。他們持續地向這些玩意中提供了大量他們的信息:喜歡什么?朋友是誰?下周做什么?現在什么心情?未來三周可能去哪玩……

        我個人就至少在網絡上使用至少20種不同的社交服務,所以說搜索引擎不能只返給我簡單的數據,而應當利用這些數據返給我我想要的內容。比如,我已經在網上吵了好幾天說我下周要去邁阿密。

        在Facebook,我創建了幾個我將要在邁阿密參加的活動;在Digg,我dugg了幾個水中呼吸器的信息;在Last.fm,我創建了幾個標題為“Miami Plane Ride”的音樂列表。在Facebook我從朋友那兒收到了幾個回帖稱我不應當錯過邁阿密的幾個酒吧和跳舞俱樂部。其他朋友推薦了那兒的幾處海灘,還給了照片。

        如果我去Google搜索跳舞俱樂部,最頂上的三個搜索結果跟我要找的一點關系都沒有。如圖:



    圖片11
        正如我說的,沒有一個搜索結果對我有用,是不是我的搜索條件太為難Google了?于是我又輸入了“Miami”,讓我們再看看結果:


    圖片22

        現在起碼我得到了一些結果能讓我看到邁阿密的跳舞俱樂部,但是哪個是朋友推薦我的呢?為什么我要的結果不能直接出現在我的面前?為什么沒有圖片,或者最好再有video?消費者的評論在哪兒呢?

        使用Live Complete Search,,輸入“跳舞俱樂部”,迅速在我的搜索結果中出現了內容,并且將結果局限到了邁阿密。并不是因為我想去邁阿密,搜索才得到這樣的結果,而是因為我twitter了我的朋友問他們邁阿密最好的跳舞俱樂部在哪兒,因此,搜索找出了我想要的結果。



    圖片33

        第一條結果是Nikki Beach,正是我朋友告訴我的那個。搜索中還有一張圖片,他們留給我的評論也能在搜索頁面中看到,還有電話號碼也以microformats的形式出現 在網頁中,我還能夠在這兒使用Twitter, Digg或者 Facebook得到更詳細的信息。而且,Live Complete Search知道我在Last.FM創建了一個Miami播放列表,所以還在搜索中加入了一個鏈接。

        當然這只是個例子,但我想從中你已經能夠看到了精髓。

    Building Live Social Profile
        Google已經證明你并不需要擁有所有的數據,因為有人會提供而Google只是幫你找到它們,令人感到發笑的是許多企業紛紛克隆Google的方法。 微軟有互聯網上第一位的IM——MSN Messenger,每個用戶都有一個Live 賬號,有些人還有Live Spaces的賬號。我不知道你怎樣,但在我看來使用Live Spaces的并不多。我點擊了一下我MSN的好友,發現很多人從未用過Live Spaces,即使有使用的人,可能使用的幾率也不及Facebook之類的百分之一。

        我的建議是微軟應當設法將Live Spaces變成人氣旺盛的(“Live”) Spaces,從而用戶可以通過互聯網將他們的社交狀況傳上去,這將創建一個終極社交檔案(social profile)和終極個人網頁(social “my page”)。


    圖片44
    建議界面(The Proposed Interface)

        建議的Live Search的界面非常簡單。它默認提供完整的搜索容量,包含互聯網上的一切并將搜索結果放在合適的位置。比如,使用完全搜索,你會得到一些網頁、 blog、帖子和一些視頻,也可能有寫Digg文章。如果只想搜索自己的社交圖呢?沒問題,只需要點擊“Social”,搜索結果馬上只呈現出與你有關的 結果。

        而且,Live Search的界面中能夠插入許多過濾器,比如“搜索”和“兒童”。學校可以管理網絡從而只允許“搜索”模式,父母可以管好自己的孩子只允許“兒童”模 式。通過Live Spaces和 Live Profile連接這些系統,微軟將創建出比Google PageRank強大許多的搜索,用戶的天平也開始擺向了這邊。



    圖片55
    搜索的最終思想(Final Thoughts on Search)

        希望你能夠意識到,社交內容、microformats、和一個能夠提供整個網絡的完美界面將是搜索的下一次飛躍。擁有更加接近社交圖的搜索結果比PageRank或者PageRank的克隆更容易統計互聯網

    posted @ 2008-11-05 21:57 bt下載 閱讀(217) | 評論 (0)編輯 收藏

    毋庸置疑,對于所有研究互聯網新媒體公司的同仁們而言,blogbus是一個絕佳的案例,他不是BT bsp。

    1,在門戶BSP大舉進攻下,專業BSP日漸沒落。blogbus偏安于上海,能發展的有聲有色,不易。剛看到Jenny發的blogbus六周年的活動。可以說,blogbus的發展路線值得所有web2.0公司學習。

     編者注:如在百度中搜索 甜性澀愛色即是空 愛的色放出現的問題說知道了。

    2,blogbus能走到現在,跟公司團隊的黃金組合關系很大。資深的互聯網人士:橫戈;資深媒體研究專家:魏武揮;資深廣告營銷界人士:jenny。我想,國內所有希望通過互聯網賺錢的web2.0公司都應該參考下這種團隊。不管是思路、見地。還有資源,客戶的說教。

    3,blogbus走出的商業模式,將是未來很長一段時間,不少國內2.0公司必須的一步。原因很簡單,中國互聯網廣告規模雖然上漲很快,但依然停留在初級階段,缺乏專業細分的廣告網絡(代理)公司推動。加上客戶認知度較低,web2.0公司必須肩負推動廣告挖掘的重任。

    4,所以,細分的廣告網絡(代理)公司在國內會越來越有前景,其中一部分會來源于公關公司的升級,另一部分會來自于當下大量掌握廣告客戶投放資源的4A公司;再有一個就是新媒體或者是社會化媒體公司自身,在這點上blogbus和feedsky都是個例子。David Wolf說,“中國的問題在于我們點子的太簡單”,其實更準確點說是缺專營的廣告營銷公司。

    5,所以,有人會問:blogbus是廣告公司,還是互聯網公司?其實,blogbus作為一個新媒體或者是社會化媒體平臺,已經聚集了百萬級的人群,背靠這些人群挖掘出了不小的商業價值,這已經說明了一切。很多更大用戶量級的公司,尚不及此。你說google是互聯網公司,還是廣告公司?除了不斷膨脹的互聯網業務,google也正在成為更大的廣告代理或分銷商。所以,我說過,新媒體要變成廣告公司

    6,blogbus最近推出的幾個業務,非常值得把玩。一個是基于blog平臺推出的SNS功能,我非常認同魏武揮的說法,因為用戶和營銷需求去增加blog平臺的互動功能,顯然SNS是增加互動關聯的成熟方式。但絕不是把blog變成一個SNS平臺。

    7,另一個更有意思的則是《城客》,簡單說,城客是一個依托于blogbus平臺的雜志;它其實是blogbus線上資源的一個延伸(內容低成本+現有用戶群),這也是我看好它的一個因素;趕巧的是,同期還有一個純粹靠整合網上內容的印刷雜志《博客天下》。形式相同,思路卻是迥異。

    8,我記得,blogbus下面還有一個做口碑營銷的“吆喝城”。

    9,blogbus會成為一種現象,尤其是在冬天。

    posted @ 2008-11-03 11:34 bt下載| 編輯 收藏

    TreeMap是紅黑樹算法的實現,實現了SortedMap接口,要注意的是它不在使用哈希表,存儲方式是一個特殊的二叉樹,有關紅黑樹:
    http://baike.baidu.com/view/133754.htm  http://www.bt285.cn

    這篇文章介紹的不錯,我之前沒有聽說過二叉樹,我就是看這篇文章加上看一下TreeMap的源代碼才搞懂紅黑樹算法的.

     

    這里不打算研究TreeMap的源代碼了,因為完全是一個算法的實現,如果對這個算法不了解,肯定看不懂,我也有很多地方不是沒有完全看明白,這里就談談TreeMap的使用吧.

     

     

    TreeMap的聲明:public class TreeMap extends AbstractMap implements SortedMap,Cloneable, java.io.Serializable
    所以我們要知道SortedMap接口:
    SortedMap表示的是一個排序的Map
    public interface SortedMap extends Map
    增加了幾個方法的定義
    SortedMap headMap(Object toKey)
    SortedMap tailMap(Object fromKey)
    SortedMap subMap(Object fromKey, Object toKey)
    Object firstKey()
    Object lastKey()

     

     

    既然TreeMap是有序的,自然要求元素是可以比較大小的,如果構造函數指定Comparator的話,就使用這個Comparator比較大小,如果沒有指定Comparator的話,就使用自然排序(元素要實現Comparable接口).如果這兩個都不可用,就等著出錯吧.

    現看一下該接口的定義:
    public interface Comparable{
       public int compareTo(Object o);
    }
    該接口定義類的自然順序,實現該接口的類就可以按這種方式排序.
    一般要求:
    e1.equals((Object)e2)和e1.compareTo((Object)e2)==0具有相同的值,
    這樣的話我們就稱自然順序就和equals一致.
    這個接口有什么用呢?
    如果數據或者List中的元素實現了該接口的話,我們就可以調用Collections.sort或者Arrays方法給他們排序.

    如果自然順序和equals不一致的話,如果出現在Sorted Map和Set里面,
    就會出現預想不到的邏輯錯誤,可能你調用add的時候添加不了,而集合里面確沒有這個元素.具體的討論要接口哈希表的應用.

     

     

     

    public interface Comparator {
      int compare(Object o1, Object o2);
      boolean equals(Object obj);
    }

    定義了兩個方法,其實我們一般都只需要實現compare方法就行了,因為類都是默認從Object繼承
    所以會使用Object的equals方法.
    Comparator一般都作為一個匿名類出現,對于沒有實現Comparable的對象的集合,排序的時候
    需要指定一個Comparator.

    這里舉例說明
    對于實現了Comparable的類我們就用最簡單的Integer
    List list=new ArrayList();
    list.add(new Integer(3));
    list.add(new Integer(53));
    list.add(new Integer(34));
    Collections.sort(list);

    對于沒有實現Comparable的,我們就用Object,按照hashCode大小來排序.
    List list= new ArrayList();
    list.add(new Object());
    list.add(new Object());
    list.add(new Object());
    Collections.sort(list,new Comparator(){ public int compare(Object o1, Object o2){
                        return (o1.hashCode()-o2.hashCode());
    })

    因為是二叉樹,所以一般查找時間復雜度為 o(lg(n)),這個效率當然沒有HashMap的效率高.不過TreeMap比HashMap功能強大,如果不需要排序的話當然不會用TreeMap,如果需要排序的話,HashMap無法勝任,當然要用TreeMap了,它可以求子Map.所以這個是適用場合問題,無法比較他們.
     
    另外,我們也習慣了,有Map就會跟一個Set,我們都可以猜到TreeSet和通過TreeMap實現的一個SortedSet的實現.不過我覺的TreeSet好像比TreeMap用的場合多一些,求子集是很常用的呀!!

    posted @ 2008-10-30 20:59 bt下載 閱讀(3288) | 評論 (1)編輯 收藏

    以前我一直以為File#renameTo(File)方法與OS下面的 move/mv 命令是相同的,可以達到改名、移動文件的目的。不過后來經常發現問題,真的很bt,File#renameTo(File)方法會返回失敗(false),文件沒有移動,又查不出原因,再后來干脆棄用該方法,自己實現一個copy方法,問題倒是再也沒有出現過。

    昨天老板同學又遇到這個問題,File#renameTo(File)方法在windows下面工作的好好的,在linux下偶爾又失靈了。回到家我掃了一遍JDK中File#renameTo(File)方法的源代碼,發現它調用的是一個本地的方法(native method),無法再跟蹤下去。網上有人說該方法在window下是正常的,在linux下面是不正常的。這個很難說通,SUN不可能搞出這種平臺不一致的代碼出來啊。

    后面在SUN的官方論壇上看到有人提到這個問題“works on windows, don't work on linux”,后面有人回復說是“file systems”不一樣。究竟怎么不一樣呢?還是沒有想出來...

    后面在一個論壇里面發現了某人關于這個問題的闡述:
    In the Unix'esque O/S's you cannot renameTo() across file systems. This behavior is different than the Unix "mv" command. When crossing file systems mv does a copy and delete which is what you'll have to do if this is the case.

    The same thing would happen on Windows if you tried to renameTo a different drive, i.e. C: -> D:
    終于明白咯。

    做個實驗:

  • File sourceFile = new File("c:/test.txt");   
  • File targetFile1 = new File("e:/test.txt");   
  • File targetFile2 = new File("d:/test.txt");   
  • System.out.println("source file is exist? " + sourceFile.exists()   
  •     + ", source file => " + sourceFile);   
  • System.out.println(targetFile1 + " is exist? " + targetFile1.exists());   
  • System.out.println("rename to " + targetFile1 + " => "  
  •     + sourceFile.renameTo(targetFile1));   
  • System.out.println("source file is exist? " + sourceFile.exists()   
  •     + ", source file => " + sourceFile);   
  • System.out.println(targetFile2 + " is exist? " + targetFile2.exists());   
  • System.out.println("rename to " + targetFile2 + " => "  
  •     + sourceFile.renameTo(targetFile2));  



  • 注意看結果,從C盤到E盤失敗了,從C盤到D盤成功了。因為我的電腦C、D兩個盤是NTFS格式的,而E盤是FAT32格式的。所以從C到E就是上面文章所說的"file systems"不一樣。從C到D由于同是NTFS分區,所以不存在這個問題,當然就成功了。

    果然是不能把File#renameTo(File)當作move方法使用。

    可以考慮使用apache組織的commons-io包里面的FileUtils#copyFile(File,File)和FileUtils#copyFileToDirectory(File,File)方法實現copy的效果。至于刪除嘛,我想如果要求不是那么精確,可以調用File#deleteOnExit()方法,在虛擬機終止的時候,刪除掉這個目錄或文件。

    BTW:File是文件和目錄路徑名的抽象表示形式,所以有可能是目錄,千萬小心。
    下面我寫的一個實現方法

    /**
      * 使用FileChannel拷貝文件
      *
      * @param srcFile
      * @param destFile
      * @throws IOException
      */
     public static void copyUseChannel(File srcFile, File destFile)
       throws IOException {
      if ((!srcFile.exists()) || (srcFile.isDirectory())) {
       return;
      }

      if (!destFile.exists()) {
       createFile(destFile.getAbsolutePath());
      }

      FileChannel out = null;
      FileChannel in = null;
      try {
       out = new FileOutputStream(destFile).getChannel();
       in = new FileInputStream(srcFile).getChannel();
       ByteBuffer buffer = ByteBuffer.allocate(102400);
       int position = 0;
       int length = 0;
       while (true) {
        length = in.read(buffer, position);
        if (length <= 0) {
         break;
        }
        // System.out.println("after read:"+buffer);
        buffer.flip();
        // System.out.println("after flip:"+buffer);
        out.write(buffer, position);
        position += length;
        buffer.clear();
        // System.out.println("after clear:"+buffer);
       }

      } finally {
       if (out != null) {
        out.close();
       }
       if (in != null) {
        in.close();
       }
      }
     }

    posted @ 2008-10-27 10:15 bt下載 閱讀(1677) | 評論 (2)編輯 收藏

    CSDN首頁推薦了一篇文章,說兩位退休的美國大學教授上書反對將Java作為編程教學語言,對此我表示高度認同。對于Java,我并不反感,而且相信它在工業應用中的地位不可取代,但是,我一直反對將Java作為主要的編程教學語言,因為教學語言承擔著與生產語言不同的任務,它必須能夠幫助學生奠定堅實的技術基礎,塑造核心技術能力。在這方面,Java不能夠勝任。

    1990年代中期以前,美國的計算機編程入門教育以Pascal為主。我的一位美國程序員朋友至今還懷念他與Pascal為伴的高中年代。到了1990年代中后期,由于ANSI C語言“糾正”了早期C語言的一些不適合編程教學的問題,因此成為很多美國高中和大學編程入門課的教學語言。1998年,美國指導編程教學的一個協會推薦將C++作為入門教學語言,在當時引起很大的反響,認為是編程教育方面的一個重要進步。但遺憾的是,C++非常復雜,而當時C++語言的教育體系又非常不成熟,因此很多地方的教學方法不得當,把學生迅速拖入無邊無際的語言細節當中,引起了學生痛苦的抱怨。大約經過兩三年不成功的實踐之后,在本世紀初,美國計算機教育界普遍接受Java作為編程入門語言。此后在很短的時間里,Java迅速成為美國高中和大學里的首選編程教學語言,老師教得輕松,學生學得甜蜜,所以這個局面一直持續到現在。

    而在中國,BASIC語言及其變體一直到1990年代中期都還是“算法語言”課程的主要教學內容,充分折射出當時中國計算機教學與工業應用之間的脫節。只是到了1990年代后期,C語言才確立了在中國工科計算機編程入門教育中的主流地位。到現在為止,大部分工科學生都“必修”“C程序設計語言”這門課程。不過事實上,根據我的了解,這門課程的總體教學質量相當糟糕,大部分學生可以說是滿懷希望而來,兩手空空而去。在這種情況下,中國高校計算機編程入門教育已經開始悄悄向Java過渡了。據我所知,有一些名校已經開始將Java設為編程入門課程,并且認為這是與國際接軌進步標志。

    在我的朋友圈子里,大多數真正的一線開發者和技術領導者,對于將Java作為入門教學語言的“發展方向”都持質疑態度。他們中很多人目前主要的工作都集中在Java上,因此這種態度并非來自所謂語言宗教情緒,而是來自他們招聘和實際工作中的感受。他們發現,只學習Java、C#、VB等“現代”編程語言的學生,精于拿來主義,長于整合和快速開發,思維活躍,生產效率高,讓他們來做直截了當的、有章可循的、非研究性和非創新性的工作比較合適,但是基礎不扎實,對計算機系統的理解薄弱,處理細節和矛盾的能力不足,一旦他們熟悉的套路用不上,則缺少自主分析問題、解決問題的知識、能力和經驗。

    今天看到兩位教授的“上書”,才知道原來他們也有同感。只不過這兩位教授說的更直白,直接反對將Java作為入門編程語言,而是冒天下之大不韙,公然號召開歷史倒車,要求退回到C、C++、Lisp和Ada去。

    我是支持兩位教授的。我認為,Java、C#、VB和其它虛擬機之上的語言都不適合作為專業程序員的入門教學語言。在中國還非常缺乏具有創新和獨立解決問題的高水平程序員的局面下,我們應該認真做好的事情是努力提高C/C++的教學質量,而不是圖快活轉向Java。

    教學語言的選擇是至關重要的事情。作為大多數學生第一種需要認真學習理解的編程語言,教學語言將會成為他們中間很多人的“編程母語”,深深地烙印在學生的思維方式中。這個編程母語要幫助學生破除計算機和軟件的神秘感,建立對于程序的基本認識和對計算機模型的最初理解。在后續專業基礎課和專業課程的學習中,這門編程語言應該作為主要工具貫穿始終,幫助學生認識計算機系統,掌握算法與數據結構技能,熟悉操作系統概念,理解編譯原理知識,理解軟件抽象及軟件設計的基本思想,完成一定量的課程及課外項目實踐,建立正確的軟件開發實踐習慣。不但如此,這種教學語言必須是工業界的主流語言,否則學生學非所用,學習動力無法保證。

    按照這個標準來衡量,Java適合于作為主要的編程教學語言嗎?我不這么認為。首先,我承認Java在教學上有一些優勢,比如其開發環境和工具支持非常成熟,有助于培養學生正確的編程習慣;Java是當今第一工業主流語言,標準類庫非常全面,可以迅速地開發具有實際用途的程序,有助于激發和保持學生的興趣;而在數據結構、算法、編譯原理的教學方面,Java也毫不落于下風,在軟件抽象設計(面向對象)方面,Java還有著明顯的優勢;特別是在并行編程的教學方面,Java 1.5 concurrency包提供的優勢是壓倒性的。盡管有如上這些優勢,但Java作為教學語言存在著一個致命的缺陷,即它是一個虛擬機語言,這一點就足以把它從教學語言的名單上去掉。作為一個虛擬機語言,Java對開發者隔絕了下層的真實系統,從而構造了一個近乎完美的環境,在這個環境里,世界上只有一種機器,一個操作系統,內存是無限的,所有的機器都具有相同的字節順序和一致的類型約定,為了設計的優美而犧牲速度永遠是正義行為,從反射到運行時自動加載,從完備的容器類到統一字符編碼,一大堆漂亮的功能都可以不費吹灰之力唾手而得。要是這個世界上每臺計算機都是一個Java機器,每項編程任務都可以在這樣一個近乎完美的環境中開發,那毫無以為,Java是最合適的編程教學語言。但是事實上呢?這樣一個完美的環境是Java力量的源泉,但這卻不是真實的世界。在真實世界里,我們可能面對非常原始的環境,苛刻的運行時限制,復雜多變的系統環境,令人窒息的細節魔鬼,要對付這些東西,需要開發者具有在應對復雜性,自己構造環境,在諸多限制條件下尋找解決方案的能力。而這種能力,被無數人無數次地證明是軟件開發、特別是軟件創新的核心能力。把Java作為教學語言,恰恰會導致這種核心能力的缺失。除此之外,如果耐心觀察的話,不難發現,幾乎在任何軟件領域里的創新性成果都首先是由C/C++語言實現的,原因很簡單,Java是站在C/C++基礎之上的,只有C/C++先把大路趟開,Java才能夠順勢而上。

    相反,盡管C/C++語言作為教學語言有很多的不足,比如不同環境下開發模式差異大,細節繁多,開發效率低,容易犯錯,測試和調試困難,學習者難以保持動力,等等,但是這些問題都可以解決。而C/C++的關鍵優點,是能夠讓學習者在真實的計算機抽象上、在大量的細節和矛盾中學會思考,學會解決問題,學會了解真實的系統,知輕重,明生死,從而建立核心能力。掌握了C/C++ bt語言,再去學習和理解Java、C#、Python、Ruby和其它語言,就比較容易達到更高的境界。反之,如果習慣了舒舒服服躺在完美世界里當闊少,那就很難有勇氣面對真實的世界。當然,很多開發者認為,現在更重要的能力是理解業務、整合現有資源的能力,而不是處理底層細節的技術。這種說法放在個人身上沒有問題,但是不能成為整個編程教育的指導思想。我們需要各個層面上的人才,精通業務和設計的架構師固然很重要,但能夠在底層作出創新成果的編程高手實際上更為稀缺和珍貴,很多時候也能夠創造更大的價值。而且,更重要的是,一個精通系統知識的開發者在往上走的時候不會遇到大的障礙,而一個只知道拼裝組合的“高級設計師”,往往連往下看的勇氣都沒有。

    Java的另外一個問題,是其所倡導的繁瑣設計風格,一個對象套一個對象,一個對象疊一個對象,概念之間彼此橫七豎八地互相依賴,人為制造出一大堆貌似精美、實則累贅的所謂設計。這個問題我已經批評過多次,并且相信這股歪風一定會最終被人們拋棄,Java最終會歸于質樸。但是在這一天到來之前,Java對于初學者來說,很可能蒙住他們的雙眼,使他們看不到軟件設計中最可貴的簡單性和優美的統一,體會不到數據和程序的統一。在這一點上,C表現的非常好,而C++如果教學得體,可以做的更好。

    當然,這并不是為現在的C/C++教學辯護。恰恰相反,從我了解的情況來看,目前普通高校的C/C++教學質量非常令人擔憂。學生學不會,而且越學越沒有興趣,老師則感到教起來很棘手,迫于現實情況往往選擇敷衍了事。反而是教Java,無論如何學生還能學到一點東西,對就業也有直接的幫助。至于學生的核心能力確實,發展后勁不足等問題,就讓他們在現實工作中自己解決吧。坦率地說,這種想法也很有道理。不過,從教學角度來說,我認為老師們還是應該積極考慮如何提高C/C++的教學質量。畢竟學生階段是十分寶貴的,基礎不在這個時期夯實,將來想彌補,就算不是完全不可能,也將付出十倍的代價。本著對學生職業生涯的負責態度,還是應該幫助學生達到這個階段應該達到的目標。在兩位教授的公開信里,也充分表達出這個意思。

    我贊成的編程教育過程,應當是以C/C++(基本上是C)為主線,貫穿起算法、數據結構、系統原理、編譯和數據處理、軟件設計和組件技術等關鍵知識領域,讓學生能夠從根本上理解現代軟件系統的原理和構造,并通過有效的練習建立正確的軟件設計觀念和良好的工程實踐習慣。在這個基礎上,無論將來是深入學習C++,還是進入Java的繁榮世界,或者擁抱Python、Ruby,甚至于走向Web開發,都會心領神會,勢如破竹。

    posted @ 2008-10-14 19:38 bt下載| 編輯 收藏

    第1章基礎知識

    1.1. 單鑰密碼體制

    單鑰密碼體制是一種傳統的加密算法,是指信息的發送方和接收方共同使用同一把密鑰進行加解密。

    通常,使用的加密算法比較簡便高效,密鑰簡短,加解密速度快,破譯極其困難。但是加密的安全性依靠密鑰保管的安全性,在公開的計算機網絡上安全地傳送和保管密鑰是一個嚴峻的問題,并且如果在多用戶的情況下密鑰的保管安全性也是一個問題。

    單鑰密碼體制的代表是美國的DES

    1.2. 消息摘要

    一個消息摘要就是一個數據塊的數字指紋。即對一個任意長度的一個數據塊進行計算,產生一個唯一指印(對于SHA1是產生一個20字節的二進制數組)。

    消息摘要有兩個基本屬性:

    • 兩個不同的報文難以生成相同的摘要
    • 難以對指定的摘要生成一個報文,而由該報文反推算出該指定的摘要

    代表:美國國家標準技術研究所的SHA1和麻省理工學院Ronald Rivest提出的MD5

    1.3. Diffie-Hellman密鑰一致協議

    密鑰一致協議是由公開密鑰密碼體制的奠基人Diffie和Hellman所提出的一種思想。

    先決條件,允許兩名用戶在公開媒體上交換信息以生成"一致"的,可以共享的密鑰

    代表:指數密鑰一致協議(Exponential Key Agreement Protocol)

    1.4. 非對稱算法與公鑰體系

    1976年,Dittie和Hellman為解決密鑰管理問題,在他們的奠基性的工作"密碼學的新方向"一文中,提出一種密鑰交換協議,允許在不安全的媒體上通過通訊雙方交換信息,安全地傳送秘密密鑰。在此新思想的基礎上,很快出現了非對稱密鑰密碼體制,即公鑰密碼體制。在公鑰體制中,加密密鑰不同于解密密鑰,加密密鑰公之于眾,誰都可以使用;解密密鑰只有解密人自己知道。它們分別稱為公開密鑰(Public key)和秘密密鑰(Private key)。

    迄今為止的所有公鑰密碼體系中,RSA系統是最著名、最多使用的一種。RSA公開密鑰密碼系統是由R.Rivest、A.Shamir和L.Adleman俊教授于1977年提出的。RSA的取名就是來自于這三位發明者的姓的第一個字母

    1.5. 數字簽名

    所謂數字簽名就是信息發送者用其私鑰對從所傳報文中提取出的特征數據(或稱數字指紋)進行RSA算法操作,以保證發信人無法抵賴曾發過該信息(即不可抵賴性),同時也確保信息報文在經簽名后末被篡改(即完整性)。當信息接收者收到報文后,就可以用發送者的公鑰對數字簽名進行驗證。 

    在數字簽名中有重要作用的數字指紋是通過一類特殊的散列函數(HASH函數)生成的,對這些HASH函數的特殊要求是:

    1. 接受的輸入報文數據沒有長度限制;
    2. 對任何輸入報文數據生成固定長度的摘要(數字指紋)輸出
    3. 從報文能方便地算出摘要;
    4. 難以對指定的摘要生成一個報文,而由該報文反推算出該指定的摘要;
    5. 兩個不同的報文難以生成相同的摘要

    代表:DSA





    回頁首


    第2章在JAVA中的實現

    2.1. 相關

    Diffie-Hellman密鑰一致協議和DES程序需要JCE工具庫的支持,可以到 http://java.sun.com/security/index.html  或是www.bt285.cn 下載JCE,并進行安裝。簡易安裝把 jce1.2.1\lib 下的所有內容復制到 %java_home%\lib\ext下,如果沒有ext目錄自行建立,再把jce1_2_1.jar和sunjce_provider.jar添加到CLASSPATH內,更詳細說明請看相應用戶手冊

    2.2. 消息摘要MD5和SHA的使用

    使用方法:

    首先用生成一個MessageDigest類,確定計算方法

    java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");

    添加要進行計算摘要的信息

    alga.update(myinfo.getBytes());

    計算出摘要

    byte[] digesta=alga.digest();

    發送給其他人你的信息和摘要

    其他人用相同的方法初始化,添加信息,最后進行比較摘要是否相同

    algb.isEqual(digesta,algb.digest())

    相關AIP

    java.security.MessageDigest 類

    static getInstance(String algorithm)

    返回一個MessageDigest對象,它實現指定的算法

    參數:算法名,如 SHA-1 或MD5

    void update (byte input)

    void update (byte[] input)

    void update(byte[] input, int offset, int len)

    添加要進行計算摘要的信息

    byte[] digest()

    完成計算,返回計算得到的摘要(對于MD5是16位,SHA是20位)

    void reset()

    復位

    static boolean isEqual(byte[] digesta, byte[] digestb)

    比效兩個摘要是否相同

    代碼:

    import java.security.*;
                public class myDigest {
                public static void main(String[] args)  {
                myDigest my=new myDigest();
                my.testDigest();
                }
                public void testDigest()
                {
                try {
                String myinfo="我的測試信息";
                //java.security.MessageDigest alg=java.security.MessageDigest.getInstance("MD5");
                java.security.MessageDigest alga=java.security.MessageDigest.getInstance("SHA-1");
                alga.update(myinfo.getBytes());
                byte[] digesta=alga.digest();
                System.out.println("本信息摘要是:"+byte2hex(digesta));
                //通過某中方式傳給其他人你的信息(myinfo)和摘要(digesta) 對方可以判斷是否更改或傳輸正常
                java.security.MessageDigest algb=java.security.MessageDigest.getInstance("SHA-1");
                algb.update(myinfo.getBytes());
                if (algb.isEqual(digesta,algb.digest())) {
                System.out.println("信息檢查正常");
                }
                else
                {
                System.out.println("摘要不相同");
                }
                }
                catch (java.security.NoSuchAlgorithmException ex) {
                System.out.println("非法摘要算法");
                }
                }
                public String byte2hex(byte[] b) //二行制轉字符串
                {
                String hs="";
                String stmp="";
                for (int n=0;n<b.length;n++)
                {
                stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
                if (stmp.length()==1) hs=hs+"0"+stmp;
                else hs=hs+stmp;
                if (n<b.length-1)  hs=hs+":";
                }
                return hs.toUpperCase();
                }
                }

    2.3. 數字簽名DSA

    1. 對于一個用戶來講首先要生成他的密鑰對,并且分別保存

      生成一個KeyPairGenerator實例

         java.security.KeyPairGenerator  keygen=java.security.KeyPairGenerator.getInstance("DSA");
                          如果設定隨機產生器就用如相代碼初始化
                      SecureRandom secrand=new SecureRandom();
                      secrand.setSeed("tttt".getBytes()); //初始化隨機產生器
                      keygen.initialize(512,secrand);     //初始化密鑰生成器
                      否則
                      keygen.initialize(512);
                      生成密鑰公鑰pubkey和私鑰prikey
                      KeyPair keys=keygen.generateKeyPair(); //生成密鑰組
                      PublicKey pubkey=keys.getPublic();
                      PrivateKey prikey=keys.getPrivate();
                      分別保存在myprikey.dat和mypubkey.dat中,以便下次不在生成
                      (生成密鑰對的時間比較長
                      java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
                           out.writeObject(prikey);
                      out.close();
                      out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
                           out.writeObject(pubkey);
                      out.close();
                      


    2. 用他私人密鑰(prikey)對他所確認的信息(info)進行數字簽名產生一個簽名數組

      從文件中讀入私人密鑰(prikey)

         java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
                          PrivateKey myprikey=(PrivateKey)in.readObject();
                      in.close();
                      初始一個Signature對象,并用私鑰對信息簽名
                      java.security.Signature signet=java.security.Signature.getInstance("DSA");
                      signet.initSign(myprikey);
                      signet.update(myinfo.getBytes());
                      byte[] signed=signet.sign();
                      把信息和簽名保存在一個文件中(myinfo.dat)
                      java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
                            out.writeObject(myinfo);
                      out.writeObject(signed);
                      out.close();
                      把他的公鑰的信息及簽名發給其它用戶
                      


    3. 其他用戶用他的公共密鑰(pubkey)和簽名(signed)和信息(info)進行驗證是否由他簽名的信息

      讀入公鑰
      java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
      PublicKey pubkey=(PublicKey)in.readObject();
      in.close();

      讀入簽名和信息
      in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
      String info=(String)in.readObject();
      byte[] signed=(byte[])in.readObject();
      in.close();

      初始一個Signature對象,并用公鑰和簽名進行驗證
      java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
      signetcheck.initVerify(pubkey);
      signetcheck.update(info.getBytes());
      if (signetcheck.verify(signed)) { System.out.println("簽名正常");}

      對于密鑰的保存本文是用對象流的方式保存和傳送的,也可可以用編碼的方式保存.注意要
      import java.security.spec.*
      import java.security.*

      具休說明如下

      • public key是用X.509編碼的,例碼如下:
          byte[] bobEncodedPubKey=mypublic.getEncoded(); //生成編碼
                            //傳送二進制編碼
                            //以下代碼轉換編碼為相應key對象
                            X509EncodedKeySpec bobPubKeySpec = new X509EncodedKeySpec(bobEncodedPubKey);
                            KeyFactory keyFactory = KeyFactory.getInstance("DSA");
                            PublicKey bobPubKey = keyFactory.generatePublic(bobPubKeySpec);
                            


      • 對于Private key是用PKCS#8編碼,例碼如下:
         byte[] bPKCS=myprikey.getEncoded();
                            //傳送二進制編碼
                            //以下代碼轉換編碼為相應key對象
                            PKCS8EncodedKeySpec priPKCS8=new PKCS8EncodedKeySpec(bPKCS);
                            KeyFactory keyf=KeyFactory.getInstance("DSA");
                            PrivateKey otherprikey=keyf.generatePrivate(priPKCS8);
                            


    4. 常用API

      java.security.KeyPairGenerator 密鑰生成器類
      public static KeyPairGenerator getInstance(String algorithm) throws NoSuchAlgorithmException
      以指定的算法返回一個KeyPairGenerator 對象
      參數: algorithm 算法名.如:"DSA","RSA"

      public void initialize(int keysize)

      以指定的長度初始化KeyPairGenerator對象,如果沒有初始化系統以1024長度默認設置

      參數:keysize 算法位長.其范圍必須在 512 到 1024 之間,且必須為 64 的倍數

      public void initialize(int keysize, SecureRandom random)
      以指定的長度初始化和隨機發生器初始化KeyPairGenerator對象
      參數:keysize 算法位長.其范圍必須在 512 到 1024 之間,且必須為 64 的倍數
      random 一個隨機位的來源(對于initialize(int keysize)使用了默認隨機器

      public abstract KeyPair generateKeyPair()
      產生新密鑰對

      java.security.KeyPair 密鑰對類
      public PrivateKey getPrivate()
      返回私鑰

      public PublicKey getPublic()
      返回公鑰

      java.security.Signature 簽名類
      public static Signature getInstance(String algorithm) throws NoSuchAlgorithmException
      返回一個指定算法的Signature對象
      參數 algorithm 如:"DSA"

      public final void initSign(PrivateKey privateKey)
      throws InvalidKeyException
      用指定的私鑰初始化
      參數:privateKey 所進行簽名時用的私鑰

      public final void update(byte data)
      throws SignatureException
      public final void update(byte[] data)
      throws SignatureException
      public final void update(byte[] data, int off, int len)
      throws SignatureException
      添加要簽名的信息

      public final byte[] sign()
      throws SignatureException
      返回簽名的數組,前提是initSign和update

      public final void initVerify(PublicKey publicKey)
      throws InvalidKeyException
      用指定的公鑰初始化
      參數:publicKey 驗證時用的公鑰

      public final boolean verify(byte[] signature)
      throws SignatureException
      驗證簽名是否有效,前提是已經initVerify初始化
      參數: signature 簽名數組

       */
                      import java.security.*;
                      import java.security.spec.*;
                      public class testdsa {
                      public static void main(String[] args) throws java.security.NoSuchAlgorithmException,java.lang.Exception {
                              testdsa my=new testdsa();
                      my.run();
                      }
                      public void run()
                      {
                      //數字簽名生成密鑰
                      //第一步生成密鑰對,如果已經生成過,本過程就可以跳過,對用戶來講myprikey.dat要保存在本地
                      //而mypubkey.dat給發布給其它用戶
                      if ((new java.io.File("myprikey.dat")).exists()==false) {
                      if (generatekey()==false) {
                      System.out.println("生成密鑰對敗");
                      return;
                      };
                      }
                      //第二步,此用戶
                      //從文件中讀入私鑰,對一個字符串進行簽名后保存在一個文件(myinfo.dat)中
                      //并且再把myinfo.dat發送出去
                      //為了方便數字簽名也放進了myifno.dat文件中,當然也可分別發送
                      try {
                      java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("myprikey.dat"));
                        PrivateKey myprikey=(PrivateKey)in.readObject();
                      in.close();
                      // java.security.spec.X509EncodedKeySpec pubX509=new java.security.spec.X509EncodedKeySpec(bX509);
                       //java.security.spec.X509EncodedKeySpec pubkeyEncode=java.security.spec.X509EncodedKeySpec
                        String myinfo="這是我的信息";    //要簽名的信息
                      //用私鑰對信息生成數字簽名
                      java.security.Signature signet=java.security.Signature.getInstance("DSA");
                      signet.initSign(myprikey);
                      signet.update(myinfo.getBytes());
                      byte[] signed=signet.sign();  //對信息的數字簽名
                      System.out.println("signed(簽名內容)="+byte2hex(signed));
                      //把信息和數字簽名保存在一個文件中
                      java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myinfo.dat"));
                        out.writeObject(myinfo);
                      out.writeObject(signed);
                      out.close();
                      System.out.println("簽名并生成文件成功");
                      }
                      catch (java.lang.Exception e) {
                      e.printStackTrace();
                      System.out.println("簽名并生成文件失敗");
                      };
                      //第三步
                      //其他人通過公共方式得到此戶的公鑰和文件
                      //其他人用此戶的公鑰,對文件進行檢查,如果成功說明是此用戶發布的信息.
                      //
                      try {
                      java.io.ObjectInputStream in=new java.io.ObjectInputStream(new java.io.FileInputStream("mypubkey.dat"));
                         PublicKey pubkey=(PublicKey)in.readObject();
                      in.close();
                      System.out.println(pubkey.getFormat());
                      in=new java.io.ObjectInputStream(new java.io.FileInputStream("myinfo.dat"));
                      String info=(String)in.readObject();
                      byte[] signed=(byte[])in.readObject();
                      in.close();
                      java.security.Signature signetcheck=java.security.Signature.getInstance("DSA");
                      signetcheck.initVerify(pubkey);
                      signetcheck.update(info.getBytes());
                      if (signetcheck.verify(signed)) {
                      System.out.println("info="+info);
                      System.out.println("簽名正常");
                      }
                      else  System.out.println("非簽名正常");
                      }
                      catch (java.lang.Exception e) {e.printStackTrace();};
                      }
                      //生成一對文件myprikey.dat和mypubkey.dat---私鑰和公鑰,
                      //公鑰要用戶發送(文件,網絡等方法)給其它用戶,私鑰保存在本地
                      public boolean generatekey()
                      {
                      try {
                      java.security.KeyPairGenerator  keygen=java.security.KeyPairGenerator.getInstance("DSA");
                       // SecureRandom secrand=new SecureRandom();
                      // secrand.setSeed("tttt".getBytes()); //初始化隨機產生器
                      // keygen.initialize(576,secrand);     //初始化密鑰生成器
                      keygen.initialize(512);
                      KeyPair keys=keygen.genKeyPair();
                      //  KeyPair keys=keygen.generateKeyPair(); //生成密鑰組
                      PublicKey pubkey=keys.getPublic();
                      PrivateKey prikey=keys.getPrivate();
                      java.io.ObjectOutputStream out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("myprikey.dat"));
                        out.writeObject(prikey);
                      out.close();
                      System.out.println("寫入對象 prikeys ok");
                      out=new java.io.ObjectOutputStream(new java.io.FileOutputStream("mypubkey.dat"));
                      out.writeObject(pubkey);
                      out.close();
                      System.out.println("寫入對象 pubkeys ok");
                      System.out.println("生成密鑰對成功");
                      return true;
                      }
                      catch (java.lang.Exception e) {
                      e.printStackTrace();
                      System.out.println("生成密鑰對失敗");
                      return false;
                      };
                      }
                      public String byte2hex(byte[] b)
                      {
                      String hs="";
                      String stmp="";
                      for (int n=0;n<b.length;n++)
                      {
                      stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
                      if (stmp.length()==1) hs=hs+"0"+stmp;
                      else hs=hs+stmp;
                      if (n<b.length-1)  hs=hs+":";
                      }
                      return hs.toUpperCase();
                      }
                      }


    2.4. DESede/DES對稱算法

    首先生成密鑰,并保存(這里并沒的保存的代碼,可參考DSA中的方法)

    KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);

    SecretKey deskey = keygen.generateKey();

    用密鑰加密明文(myinfo),生成密文(cipherByte)

    Cipher c1 = Cipher.getInstance(Algorithm);

    c1.init(Cipher.ENCRYPT_MODE,deskey);

    byte[] cipherByte=c1.doFinal(myinfo.getBytes());

    傳送密文和密鑰,本文沒有相應代碼可參考DSA

    .............

    用密鑰解密密文

    c1 = Cipher.getInstance(Algorithm);

    c1.init(Cipher.DECRYPT_MODE,deskey);

    byte[] clearByte=c1.doFinal(cipherByte);

    相對來說對稱密鑰的使用是很簡單的,對于JCE來講支技DES,DESede,Blowfish三種加密術

    對于密鑰的保存各傳送可使用對象流或者用二進制編碼,相關參考代碼如下

       SecretKey deskey = keygen.generateKey();
                byte[] desEncode=deskey.getEncoded();
                javax.crypto.spec.SecretKeySpec destmp=new javax.crypto.spec.SecretKeySpec(desEncode,Algorithm);
                   SecretKey mydeskey=destmp;

    相關API

    KeyGenerator 在DSA中已經說明,在添加JCE后在instance進可以如下參數

    DES,DESede,Blowfish,HmacMD5,HmacSHA1

    javax.crypto.Cipher 加/解密器

    public static final Cipher getInstance(java.lang.String transformation)
                throws java.security.NoSuchAlgorithmException,
                NoSuchPaddingException

    返回一個指定方法的Cipher對象

    參數:transformation 方法名(可用 DES,DESede,Blowfish)

    public final void init(int opmode, java.security.Key key)
    throws java.security.InvalidKeyException

    用指定的密鑰和模式初始化Cipher對象

    參數:opmode 方式(ENCRYPT_MODE, DECRYPT_MODE, WRAP_MODE,UNWRAP_MODE)

    key 密鑰

    public final byte[] doFinal(byte[] input)
                throws java.lang.IllegalStateException,
                IllegalBlockSizeException,
                BadPaddingException
                

    對input內的串,進行編碼處理,返回處理后二進制串,是返回解密文還是加解文由init時的opmode決定

    注意:本方法的執行前如果有update,是對updat和本次input全部處理,否則是本inout的內容

    /*
                安全程序 DESede/DES測試
                */
                import java.security.*;
                import javax.crypto.*;
                public class testdes {
                public static void main(String[] args){
                testdes my=new testdes();
                my.run();
                }
                public  void run() {
                //添加新安全算法,如果用JCE就要把它添加進去
                Security.addProvider(new com.sun.crypto.provider.SunJCE());
                String Algorithm="DES"; //定義 加密算法,可用 DES,DESede,Blowfish
                String myinfo="要加密的信息";
                try {
                //生成密鑰
                KeyGenerator keygen = KeyGenerator.getInstance(Algorithm);
                SecretKey deskey = keygen.generateKey();
                //加密
                System.out.println("加密前的二進串:"+byte2hex(myinfo.getBytes()));
                System.out.println("加密前的信息:"+myinfo);
                Cipher c1 = Cipher.getInstance(Algorithm);
                c1.init(Cipher.ENCRYPT_MODE,deskey);
                byte[] cipherByte=c1.doFinal(myinfo.getBytes());
                System.out.println("加密后的二進串:"+byte2hex(cipherByte));
                //解密
                c1 = Cipher.getInstance(Algorithm);
                c1.init(Cipher.DECRYPT_MODE,deskey);
                byte[] clearByte=c1.doFinal(cipherByte);
                System.out.println("解密后的二進串:"+byte2hex(clearByte));
                System.out.println("解密后的信息:"+(new String(clearByte)));
                }
                catch (java.security.NoSuchAlgorithmException e1) {e1.printStackTrace();}
                catch (javax.crypto.NoSuchPaddingException e2) {e2.printStackTrace();}
                catch (java.lang.Exception e3) {e3.printStackTrace();}
                }
                public String byte2hex(byte[] b) //二行制轉字符串
                {
                String hs="";
                String stmp="";
                for (int n=0;n<b.length;n++)
                {
                stmp=(java.lang.Integer.toHexString(b[n] & 0XFF));
                if (stmp.length()==1) hs=hs+"0"+stmp;
                else hs=hs+stmp;
                if (n<b.length-1)  hs=hs+":";
                }
                return hs.toUpperCase();
                }
                }


    2.5. Diffie-Hellman密鑰一致協議

    公開密鑰密碼體制的奠基人Diffie和Hellman所提出的 "指數密鑰一致協議"(Exponential Key Agreement Protocol),該協議不要求別的安全性先決條件,允許兩名用戶在公開媒體上交換信息以生成"一致"的,可以共享的密鑰。在JCE的中實現用戶alice生成DH類型的密鑰對,如果長度用1024生成的時間請,推薦第一次生成后保存DHParameterSpec,以便下次使用直接初始化.使其速度加快

    System.out.println("ALICE: 產生 DH 對 ...");
                KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
                aliceKpairGen.initialize(512);
                KeyPair aliceKpair = aliceKpairGen.generateKeyPair();

    alice生成公鑰發送組bob

    byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();

    bob從alice發送來的公鑰中讀出DH密鑰對的初始參數生成bob的DH密鑰對

    注意這一步一定要做,要保證每個用戶用相同的初始參數生成的

       DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();
                KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
                bobKpairGen.initialize(dhParamSpec);
                KeyPair bobKpair = bobKpairGen.generateKeyPair();

    bob根據alice的公鑰生成本地的DES密鑰

       KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
                bobKeyAgree.init(bobKpair.getPrivate());
                bobKeyAgree.doPhase(alicePubKey, true);
                SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");

    bob已經生成了他的DES密鑰,他現把他的公鑰發給alice,

          byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();

    alice根據bob的公鑰生成本地的DES密鑰

           ,,,,,,解碼
                KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
                aliceKeyAgree.init(aliceKpair.getPrivate());
                aliceKeyAgree.doPhase(bobPubKey, true);
                SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");

    bob和alice能過這個過程就生成了相同的DES密鑰,在這種基礎就可進行安全能信

    常用API

    java.security.KeyPairGenerator 密鑰生成器類
    public static KeyPairGenerator getInstance(String algorithm)
    throws NoSuchAlgorithmException
    以指定的算法返回一個KeyPairGenerator 對象
    參數: algorithm 算法名.如:原來是DSA,現在添加了 DiffieHellman(DH)

    public void initialize(int keysize)
    以指定的長度初始化KeyPairGenerator對象,如果沒有初始化系統以1024長度默認設置
    參數:keysize 算法位長.其范圍必須在 512 到 1024 之間,且必須為 64 的倍數
    注意:如果用1024生長的時間很長,最好生成一次后就保存,下次就不用生成了

    public void initialize(AlgorithmParameterSpec params)
    throws InvalidAlgorithmParameterException
    以指定參數初始化

    javax.crypto.interfaces.DHPublicKey
    public DHParameterSpec getParams()
    返回
    java.security.KeyFactory

    public static KeyFactory getInstance(String algorithm)
    throws NoSuchAlgorithmException
    以指定的算法返回一個KeyFactory
    參數: algorithm 算法名:DSH,DH

    public final PublicKey generatePublic(KeySpec keySpec)
    throws InvalidKeySpecException
    根據指定的key說明,返回一個PublicKey對象

    java.security.spec.X509EncodedKeySpec
    public X509EncodedKeySpec(byte[] encodedKey)
    根據指定的二進制編碼的字串生成一個key的說明
    參數:encodedKey 二進制編碼的字串(一般能過PublicKey.getEncoded()生成)
    javax.crypto.KeyAgreement 密碼一至類

    public static final KeyAgreement getInstance(java.lang.String algorithm)
    throws java.security.NoSuchAlgorithmException
    返回一個指定算法的KeyAgreement對象
    參數:algorithm 算法名,現在只能是DiffieHellman(DH)

    public final void init(java.security.Key key)
    throws java.security.InvalidKeyException
    用指定的私鑰初始化
    參數:key 一個私鑰

    public final java.security.Key doPhase(java.security.Key key,
    boolean lastPhase)
    throws java.security.InvalidKeyException,
    java.lang.IllegalStateException
    用指定的公鑰進行定位,lastPhase確定這是否是最后一個公鑰,對于兩個用戶的
    情況下就可以多次定次,最后確定
    參數:key 公鑰
    lastPhase 是否最后公鑰

    public final SecretKey generateSecret(java.lang.String algorithm)
    throws java.lang.IllegalStateException,
    java.security.NoSuchAlgorithmException,
    java.security.InvalidKeyException
    根據指定的算法生成密鑰
    參數:algorithm 加密算法(可用 DES,DESede,Blowfish)

    */
                import java.io.*;
                import java.math.BigInteger;
                import java.security.*;
                import java.security.spec.*;
                import java.security.interfaces.*;
                import javax.crypto.*;
                import javax.crypto.spec.*;
                import javax.crypto.interfaces.*;
                import com.sun.crypto.provider.SunJCE;
                public class testDHKey {
                public static void main(String argv[]) {
                try {
                testDHKey my= new testDHKey();
                my.run();
                } catch (Exception e) {
                System.err.println(e);
                }
                }
                private void run() throws Exception {
                Security.addProvider(new com.sun.crypto.provider.SunJCE());
                System.out.println("ALICE: 產生 DH 對 ...");
                KeyPairGenerator aliceKpairGen = KeyPairGenerator.getInstance("DH");
                aliceKpairGen.initialize(512);
                KeyPair aliceKpair = aliceKpairGen.generateKeyPair(); //生成時間長
                // 張三(Alice)生成公共密鑰 alicePubKeyEnc 并發送給李四(Bob) ,
                //比如用文件方式,socket.....
                byte[] alicePubKeyEnc = aliceKpair.getPublic().getEncoded();
                //bob接收到alice的編碼后的公鑰,將其解碼
                KeyFactory bobKeyFac = KeyFactory.getInstance("DH");
                X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec  (alicePubKeyEnc);
                PublicKey alicePubKey = bobKeyFac.generatePublic(x509KeySpec);
                System.out.println("alice公鑰bob解碼成功");
                // bob必須用相同的參數初始化的他的DH KEY對,所以要從Alice發給他的公開密鑰,
                //中讀出參數,再用這個參數初始化他的 DH key對
                //從alicePubKye中取alice初始化時用的參數
                DHParameterSpec dhParamSpec = ((DHPublicKey)alicePubKey).getParams();
                KeyPairGenerator bobKpairGen = KeyPairGenerator.getInstance("DH");
                bobKpairGen.initialize(dhParamSpec);
                KeyPair bobKpair = bobKpairGen.generateKeyPair();
                System.out.println("BOB: 生成 DH key 對成功");
                KeyAgreement bobKeyAgree = KeyAgreement.getInstance("DH");
                bobKeyAgree.init(bobKpair.getPrivate());
                System.out.println("BOB: 初始化本地key成功");
                //李四(bob) 生成本地的密鑰 bobDesKey
                bobKeyAgree.doPhase(alicePubKey, true);
                SecretKey bobDesKey = bobKeyAgree.generateSecret("DES");
                System.out.println("BOB: 用alice的公鑰定位本地key,生成本地DES密鑰成功");
                // Bob生成公共密鑰 bobPubKeyEnc 并發送給Alice,
                //比如用文件方式,socket.....,使其生成本地密鑰
                byte[] bobPubKeyEnc = bobKpair.getPublic().getEncoded();
                System.out.println("BOB向ALICE發送公鑰");
                // alice接收到 bobPubKeyEnc后生成bobPubKey
                // 再進行定位,使aliceKeyAgree定位在bobPubKey
                KeyFactory aliceKeyFac = KeyFactory.getInstance("DH");
                x509KeySpec = new X509EncodedKeySpec(bobPubKeyEnc);
                PublicKey bobPubKey = aliceKeyFac.generatePublic(x509KeySpec);
                System.out.println("ALICE接收BOB公鑰并解碼成功");
                ;
                KeyAgreement aliceKeyAgree = KeyAgreement.getInstance("DH");
                aliceKeyAgree.init(aliceKpair.getPrivate());
                System.out.println("ALICE: 初始化本地key成功");
                aliceKeyAgree.doPhase(bobPubKey, true);
                // 張三(alice) 生成本地的密鑰 aliceDesKey
                SecretKey aliceDesKey = aliceKeyAgree.generateSecret("DES");
                System.out.println("ALICE: 用bob的公鑰定位本地key,并生成本地DES密鑰");
                if (aliceDesKey.equals(bobDesKey)) System.out.println("張三和李四的密鑰相同");
                //現在張三和李四的本地的deskey是相同的所以,完全可以進行發送加密,接收后解密,達到
                //安全通道的的目的
                /*
                * bob用bobDesKey密鑰加密信息
                */
                Cipher bobCipher = Cipher.getInstance("DES");
                bobCipher.init(Cipher.ENCRYPT_MODE, bobDesKey);
                String bobinfo= "這是李四的機密信息";
                System.out.println("李四加密前原文:"+bobinfo);
                byte[] cleartext =bobinfo.getBytes();
                byte[] ciphertext = bobCipher.doFinal(cleartext);
                /*
                * alice用aliceDesKey密鑰解密
                */
                Cipher aliceCipher = Cipher.getInstance("DES");
                aliceCipher.init(Cipher.DECRYPT_MODE, aliceDesKey);
                byte[] recovered = aliceCipher.doFinal(ciphertext);
                System.out.println("alice解密bob的信息:"+(new String(recovered)));
                if (!java.util.Arrays.equals(cleartext, recovered))
                throw new Exception("解密后與原文信息不同");
                System.out.println("解密后相同");
                }
                }
    posted @ 2008-10-13 19:31 bt下載| 編輯 收藏

    關于應用服務器和web服務器的整合,有很多的資料了,可是都講的半生不熟的。根據這幾天整合tomcat 和 iis 的經驗,再次聊聊這個話題。

    首先我們應該對應用服務器和web服務器有一個清晰的概念。所謂的應用服務器,就是提供應用的服務器,這里的應用有很多,比如java應用,ruby 應用,或者 c#應用。

    那么什么是web服務器呢?就是提供了web功能的服務器,主要就是http服務,包括圖片的下載,等等一系列和web相關的。

    好吧,你會問為什么我們不能直接使用應用服務器呢?應用服務器也提供了http服務,比如tomcat。

    那么我們從實際出發。當你瀏覽一個網頁的時候,什么情況下你會覺得速度很慢?我們僅僅考慮頁面本身。那當然是圖片越多顯示得越慢。

    好吧,我們至少認識到一點,一些靜態資源,例如圖片,會嚴重影響頁面打開的速度。當然,這僅僅是一個方面。

    那么web服務器有什么用呢?web服務器一個優點就是在處理靜態信息上。例如一些靜態的html,圖片,等等其他靜態的東西。

    那為什么tomcat不能具備這些優點?這個問題我們可以換一個說法:為什么會計不能做市場營銷呢?

    所以嘛,大家要分工明確,應用服務器就做好它該做的:如何解釋一個jsp,如何處理java文件等等,做好這一點就足夠了。而web服務器也做好它該做的:如何快速向瀏覽器傳遞信息,如何快速地讓瀏覽器下載圖片。

    那你又問了,那為啥tomcat還提供一個http服務?那不是讓你開發方便嘛!千萬別把tomcat的http服務當成是一個web服務器。

    說了這么多,那么我們對應用服務器和web服務器的整合也應該心里有數了。就拿tomcat和iis整合來說事吧!

    我們到底想干什么呢?很明顯,我們想讓tomcat 處理對 java應用的請求,而iis應該處理圖片,css 等等其他靜態資源的事情。

    具體的細節不談了,無非就是配置 ispai_redirect 這個東東。因為我們主要說的分工問題,所以還是說說這個 uriworkermap.properties 文件。

    這個文件就是處理分工的用的。例如我定義成如下這個樣子:
    /www.5a520.cn /eshop/*.do=ajp13
    /www.5a520.cn /eshop/dwr/interface/*=ajp13
    /www.5a520.cn /eshop/dwr/*=ajp13
    /www.bt285.cn /eshop/js/*=ajp13

    那么就告訴了 isapi_redirect , 以上4種請求,都交給tomcat處理。
    那么其他的請求呢?當然是交給 iis了。

    如果我定義成這個樣子:
    /* = ajp13

    這下可慘了,iis被你浪費了,就好像你招聘了一個會計和一個推銷的人員,但是讓會計干財務的活之外,還干了推銷。而推銷人員給閑置了。

    至于 uriworkermap.properties  的詳細配置,可以參考 tomcat 網站,上面有詳細的講解。


    兩種服務器的整合雖然不難,但是如果不明白其中的意義和原理,一旦項目配置有所變化,那就是沒有葫蘆就畫不出來瓢了。
    posted @ 2008-10-08 21:17 bt下載| 編輯 收藏

    mysql slow log 是用來記錄執行時間較長(超過long_query_time秒)的sql的一種日志工具.

    啟用 slow log

    有兩種啟用方式:
    1, 在my.cnf 里 通過 log-slow-queries[=file_name]
    2, 在mysqld進程啟動時,指定--log-slow-queries[=file_name]選項

    比較的五款常用工具

    mysqldumpslow, mysqlsla, myprofi, mysql-explain-slow-log, mysqllogfilter


    mysqldumpslow, mysql官方提供的慢查詢日志分析工具. 輸出圖表如下:
    主要功能是, 統計不同慢sql的
    出現次數(Count), 
    執行最長時間(Time), 
    累計總耗費時間(Time), 
    等待鎖的時間(Lock), 
    發送給客戶端的行總數(Rows), 
    掃描的行總數(Rows), 
    用戶以及sql語句本身(抽象了一下格式, 比如 limit 1, 20 用 limit N,N 表示).

    mysqlsla, hackmysql.com推出的一款日志分析工具(該網站還維護了 mysqlreport, mysqlidxchk 等比較實用的mysql工具)
    整體來說, 功能非常強大. 數據報表,非常有利于分析慢查詢的原因, 包括執行頻率, 數據量, 查詢消耗等.

    格式說明如下:
    總查詢次數 (queries total), 去重后的sql數量 (unique)
    輸出報表的內容排序(sorted by)
    最重大的慢sql統計信息, 包括 平均執行時間, 等待鎖時間, 結果行的總數, 掃描的行總數.

    Count, sql的執行次數及占總的slow log數量的百分比.
    Time, 執行時間, 包括總時間, 平均時間, 最小, 最大時間, 時間占到總慢sql時間的百分比.
    95% of Time, 去除最快和最慢的sql, 覆蓋率占95%的sql的執行時間.
    Lock Time, 等待鎖的時間.
    95% of Lock , 95%的慢sql等待鎖時間.
    Rows sent, 結果行統計數量, 包括平均, 最小, 最大數量.
    Rows examined, 掃描的行數量.
    Database, 屬于哪個數據庫
    Users, 哪個用戶,IP, 占到所有用戶執行的sql百分比

    Query abstract, 抽象后的sql語句
    Query sample, sql語句

    除了以上的輸出, 官方還提供了很多定制化參數, 是一款不可多得的好工具.

    mysql-explain-slow-log, 德國人寫的一個perl腳本.
    http://www.willamowius.de/mysql-tools.html

    功能上有點瑕疵, 不僅把所有的 slow log 打印到屏幕上, 而且統計也只有數量而已. 不推薦使用.
    mysql-log-filter, google code上找到的一個分析工具.提供了 python 和 php 兩種可執行的腳本.
    http://code.google.com/p/mysql-log-filter/
    功能上比官方的mysqldumpslow, 多了查詢時間的統計信息(平均,最大, 累計), 其他功能都與 mysqldumpslow類似.
    特色功能除了統計信息外, 還針對輸出內容做了排版和格式化, 保證整體輸出的簡潔. 喜歡簡潔報表的朋友, 推薦使用一下.
    myprofi, 純php寫的一個開源分析工具.項目在 sourceforge 上.
    http://myprofi.sourceforge.net/

    功能上, 列出了總的慢查詢次數和類型, 去重后的sql語句, 執行次數及其占總的slow log數量的百分比.
    從整體輸出樣式來看, 比mysql-log-filter還要簡潔. 省去了很多不必要的內容. 對于只想看sql語句及執行次數的用戶來說, 比較推薦.

    總結

    工具/功能 一般統計信息 高級統計信息 腳本 優勢
    mysqldumpslow 支持 不支持 perl mysql官方自帶
    mysqlsla 支持 支持 perl 功能強大,數據報表齊全,定制化能力強.
    mysql-explain-slow-log 支持 不支持 perl
    mysql-log-filter 支持 部分支持 python or php 不失功能的前提下,保持輸出簡潔
    myprofi 支持 不支持 php 非常精簡
    posted @ 2008-10-07 23:33 bt下載| 編輯 收藏

    一、Java編碼是怎么回事?

    對于使用中文以及其他非拉丁語系語言的開發人員來說,經常會遇到字符集編碼問題。對于Java語言來說,在其內部使用的是UCS2編碼(2個字節的Unicode編碼)。這種編碼并不屬于某個語系的語言編碼,它實際上是一種編碼格式的世界語。在這個世界上所有可以在計算機中使用的語言都有對應的UCS2編碼

    正是因為Java采用了UCS2,因此,在Java中可以使用世界上任何國家的語言來為變量名、方法名、類起名,如下面代碼如下:


    class 中國
    {
        
    public String 雄起()
        {
             
    return "中國雄起";
        }
    }

    中國 祖國 
    = new 中國();
    System.out.println(祖國.雄起());

        哈哈,是不是有點象“中文編程”。實際上,也可以使用其他的語言來編程,如下面用韓文和日文來定義個類:

    class ???
    {
        
    public void スーパーマン() {  }
    }

        實際上,由于Java內部使用的是UCS2編碼格式,因為,Java并不關心所使用的是哪種語言,而只要這種語言在UCS2中有定義就可以。

        UCS2編碼中為不同國家的語言進行了分頁,這個分頁也叫“代碼頁”或“編碼頁”。中文根據包含中文字符的多少,分了很多代碼頁,如cp935cp936等,然而,這些都是在UCS2中的代碼頁名,而對于操作系統來說,如微軟的windows,一開始的中文編碼為GB2312,后來擴展成了GBK。其實GBKcp936是完全等效的,用它們哪個都行。

    二、Java編碼轉換

       
    上面說了這么多,在這一部分我們做一些編碼轉換,看看會發生什么事情。

        先定義一個字符串變量:

        String gbk = "
    中國"; // “中國”在Java內部是以UCS2格式保存的

        用下面的語言輸出一定會輸出中文:

    System.out.println(gbk);

        實現上,當我們從IDE輸入“中國”時,用的是java源代碼文件保存的格式,一般是GBK,有時也可是utf-8,而在Java編譯程序時,會不由分說地將所有的編碼格式轉換成utf-8編碼,讀者可以用UltraEdit或其他的二進制編輯器打開上面的“中國.class”,看看所生成的二進制是否有utf-8的編碼(utf-8ucs2之間的轉換非常容易,因為utf-8ucs2之間是用公式進行轉換的,而不是到代碼頁去查,這就相當于將二進制轉成16進制一樣,4個字節一組)。如“中國”的utf-8編碼按著GBK解析就是“涓  浗”。如下圖所示。



    如果使用下面的語言可以獲得“中國”的utf-8字節,結果是6(一個漢字由3個字節組成)

    System.out.println(gbk.getBytes("utf-8").length);

    下面的代碼將輸出“涓  浗”。

    System.out.println(new String(gbk.getBytes("utf-8"), "gbk"));   

    由于將“中國“的utf-8編碼格式按著gbk解析,所以會出現亂碼。

    如果要返回中文的UCS2編碼,可以使用下面的代碼:

    System.out.println(gbk.getBytes("unicode")[2]);

    System.out.println(gbk.getBytes("unicode")[3]);

    前兩個字節是標識位,要從第3個字節開始。還有就是其他的語言使用的編碼的字節順序可能不同,如在C#中可以使用下面的代碼獲得“中國“的UCS2編碼:

    String s = "
    ";

    MessageBox.Show(ASCIIEncoding.Unicode.GetBytes(s)[0].ToString());

    MessageBox.Show(ASCIIEncoding.Unicode.GetBytes(s)[1].ToString());

        使用上面的java代碼獲得的“中“的16進制UCS2編碼為4E2D,而使用C#獲得的相應的ucs2編碼為2D4E,這只是C#Java編碼內部使用的問題,并沒有什么關系。但在C#Java互操作時要注意這一點。

        如果使用下面的java編碼將獲得16進制的“中”的GBK編碼:

    System.out.println(Integer.toHexString(0xff & xyz.getBytes("gbk")[0]));

    System.out.println(Integer.toHexString(0xff & xyz.getBytes("gbk")[1]));

    “中”的ucs2編碼為2D4EGBK編碼為D6D0

        讀者可訪問如下的url自行查驗:

        http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP936.TXT

        當然,感興趣的讀者也可以試試其他語言的編碼,如“人類”的韓語是“???”,如下面的代碼將輸出“???”的cp949ucs2編碼,其中cp949是韓語的代碼頁。


    String korean = "???"// 共三個韓文字符,我們只測試第一個“?”

    System.out.println(Integer.toHexString(
    0xff & korean.getBytes("unicode")[2]));

    System.out.println(Integer.toHexString(
    0xff & korean.getBytes("unicode")[3]));

    System.out.println(Integer.toHexString(
    0xff & korean.getBytes("Cp949")[0]));

    System.out.println(Integer.toHexString(
    0xff & korean.getBytes("Cp949")[1]));

     

    上面代碼的輸出結果如下:

    c7

    78

    c0

    ce

        也就是說“?”的ucs2編碼為C778cp949的編碼為C0CE,要注意的是,在cp949中,ucs2編碼也有C0CE,不要弄混了。讀者可以訪問下面的url來驗證:

    http://unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP949.TXT

    http://www.bt285.cn/content.php?id=1196863

    Java支持的編碼格式

    三、屬性文件

    Java中的屬性文件只支持iso-8859-1編碼格式,因此,要想在屬性文件中保存中文,就必須使用UCS2編碼格式("uxxxx),因此,出現了很多將這種編碼轉換成可視編碼和工具,如Eclipse中的一些屬性文件編輯插件。

    實際上,"uxxxx編碼格式在javaC#中都可以使用,如下面的語句所示:

    String name= ""u7528"u6237"u540d"u4e0d"u80fd"u4e3a"u7a7a" ;

    System.out.println(name);

        上面代碼將輸出“用戶名不能為空”的信息。將"uxxxx格式顯示成中文非常簡單,那么如何將中文還原成"uxxxxx格式呢?下面的代碼完成了這個工作:


    String ss = "用戶名不能為空";
    byte[] uncode = ss.getBytes("Unicode");
    int x = 0xff;
    String result 
    ="";
    for(int i= 2; i < uncode.length; i++)
    {
        
    if(i % 2 == 0) result += "\\u";
        String abc 
    = Integer.toHexString(x & uncode[i]);            
        result 
    += abc.format("%2s", abc).replaceAll(" ""0");               
    }
    System.out.println(result);

     

        上面的代碼將輸出如下結果:


    \u7528\u6237\u540d\u4e0d\u80fd\u4e3a\u7a7a

        好了,現在可以利用這個技術來實現一個屬性文件編輯器了。

    四、Web中的編碼問題

        大家碰到最多的編碼問題就是在Web應用中。先讓我們看看下面的程序:

     

    <!--  main.jsp  -->

      
    <%@ page language="java"  pageEncoding="utf-8"%>

      
    <html>
          
    <head>

          
    </head>

          
    <body>
              
    <form action="servlet/MyPost" method="post">
                  
    <input type="text" name="user" />
                  
    <p/>
                  
    <input type="submit"  value="提交"/>
              
    </form>

          
    </body>
      
    </html>


        下面是個Servlet

      package servlet;

      import java.io.IOException;
      import java.io.PrintWriter;
      import javax.servlet.ServletException;
      import javax.servlet.http.HttpServlet;
      import javax.servlet.http.HttpServletRequest;
      import javax.servlet.http.HttpServletResponse;

      
    public class MyPost extends HttpServlet
      {

          
    public void doPost(HttpServletRequest request, HttpServletResponse response)
                  throws ServletException, IOException
          {
              String user 
    = request.getParameter("user");
              System.
    out.println(user);
          }
      }


        如果中main.jsp中輸入中文后,向MyPost提交,在控制臺中會輸出“中å?½”,一看就是亂碼。如果將IE的當前編碼設成其他的,如由utf-8改為gbk,仍然會出現亂碼,只是亂得不一樣而已。這是因為客戶端提交數據時是根據瀏覽器當前的編碼格式來提交的,如瀏覽器當前為gbk編碼,就以gbk編碼格式來提交。 這本身是不會出現亂碼的,問題就出在Web服務器接收數據的時候,HttpServletRequest在將客戶端傳來的數據轉成ucs2上出了問題。在默認情況下,是按著iso-8859-1編碼格式來轉的,而這種編碼格式并不支持中文,所以也就無法正常顯示中文了,解決這個問題的方法是用和客戶端瀏覽器當前編碼格式一致的編碼來轉換,如果是utf-8,則在doPost方法中應該用以下的語句來處理:

        request.setCharacterEncoding("utf-8");

        為了對每一個Servlet都起作用,可以將上面的語句加到filter里。

        另外,我們一般使用象MyEclipse一樣的IDE來編寫jsp文件,這樣的工具會根據pageEncoding屬性將jsp文件保存成相應的編碼格式,但如果要使用象記事本一樣的簡單的編輯器來編寫jsp文件,如果pageEncodingutf-8,而在默認時,記事本會將文件保存成iso-8859-1ascii)格式,但在myeclipse里,如果文件中有中文,它是不允許我們保存成不支持中文的編碼格式的,但記事本并不認識jsp,因此,這時在ie中就無法正確顯示出中文了。除非用記事本將其保存在utf-8格式。如下圖:


     

    http://blog.csdn.net/wangdei/archive/2008/10/07/3030758.aspx
    posted @ 2008-10-07 22:36 bt下載 閱讀(513) | 評論 (0)編輯 收藏

         摘要: 在沒有使用Spring提供的Open Session In View情況下,因需要在service(or Dao)層里把session關閉,所以lazy loading 為true的話,要在應用層內把關系集合都初始化,如 company.getEmployees(),否則Hibernate拋session already closed Exception;    Op...  閱讀全文
    posted @ 2008-10-05 15:01 bt下載| 編輯 收藏

    主站蜘蛛池模板: 香蕉国产在线观看免费| 亚洲精品影院久久久久久| 在线亚洲午夜片AV大片| 最好看的中文字幕2019免费| 亚洲精品综合一二三区在线 | 免费VA在线观看无码| 久久经典免费视频| 亚洲黄色在线视频| 久久精品免费观看| 国产国拍亚洲精品mv在线观看| 五月天国产成人AV免费观看| 免费又黄又爽的视频| 亚洲а∨精品天堂在线| 免费精品一区二区三区在线观看 | 国产成人精品亚洲| 麻豆国产入口在线观看免费| 中文亚洲AV片不卡在线观看| 97国免费在线视频| 久久被窝电影亚洲爽爽爽| 国内精品免费久久影院| 国产亚洲色婷婷久久99精品91| 一个人看的免费观看日本视频www| 国产免费小视频在线观看| 污视频网站在线观看免费| 免费国产a国产片高清| 国产精品亚洲一区二区三区| 麻豆最新国产剧情AV原创免费| 亚洲日韩中文字幕| 日本黄网站动漫视频免费| 91亚洲自偷手机在线观看| 亚洲高清视频免费| 亚洲精品无码mⅴ在线观看| 尤物永久免费AV无码网站| 人妻无码中文字幕免费视频蜜桃| 在线观看亚洲成人| 成人免费区一区二区三区| 亚洲日本乱码一区二区在线二产线 | 足恋玩丝袜脚视频免费网站| 黑人精品videos亚洲人| 一区二区三区免费电影| 久久夜色精品国产亚洲|