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

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

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

    java思維

    正在學習中:(

    2006年11月16日 #

    bcb6 中安裝 boost

    正則表達式是一種模式匹配形式,它通常用在處理的文本程序中。比如我們經常使用的grep工具,還是perl語言都使用了正則表達式。傳統的C++處理正則表達式是非常麻煩的,這也成為很多其他語言愛好者的笑柄,現在情況不一樣了,因為有了boost。
    Boost是一個基于Template的開發源代碼庫,在這個庫中有很多子庫用來高效處理各方面的問題,比如字符串拆分,格式化,線程等等,Boost對于每一個C++愛好者都是應該了解的,對于C++ Builder用戶如果能在熟練使用VCL的情況下再熟練使用Boost,我想一定如虎添翼。
    一般來說,使用Boost是非常簡單,和使用其他STL庫沒有太大區別,但使用Boost的正則表達式庫則不那么容易,因為這個庫還需要我們單獨編譯,下面我將詳細介紹如何使用。
    如果你還不知道或者還沒有Boost的話,你可以去www.boost.org下載最新版本,作者使用的是1.30版本。將下載下來的zip包[1]解壓到任何你喜歡的目錄,比如D:\boost。
    編譯正則表達式庫
    前面已經提到,這個庫需要我們單獨編譯才能使用,為什么不編譯好一起發布呢?主要是考慮到不同的編譯器需要不同的鏈接庫文件和鏈接庫太大了。在命令行下,進入[%Boost]\Libs\RegEx\Build目錄,直接敲入make –fbcb6.mak命令開始編譯,這里請大家注意了,如果你的計算機上同時安裝了BCB5,請一定要把path設置成為BCB6的bcc32.exe程序所在的目錄,否則可能使用BCB5的make程序,這樣雖然能編譯但最后不能使用。
    編譯過程相當耗時,你需要耐心等待,最終編譯完成,會在[%Boost]\Libs\RegEx\Build目錄生成一個BCB6目錄,在這個目錄生成了很多lib文件和dll文件,把所有dll文件復制到windows系統目錄,所以lib文件復制到bcb6\lib目錄。如果你不想這么麻煩的復制文件,可以在編譯時加入install參數,就像這樣make –fBcb6.mak install,不過作者還是比較喜歡前一種方式,這樣我可以知道到底生成了什么文件。現在編譯已經完成了,你可以體現boost的神奇魅力了。
    #include<deque>
    #include<iostream>
    #include<algorithm>
    #include<boost/regex.hpp>
    int main()
    {
    using namespace boost;
    using namespace std;
    regex expression("\\s+href\\s*=\\s*\"([^\"]*)\"",regbase::normal|regbase::icase);
    string s="<a href=\"index.html\"><img src=\"logo.gif\"></a>";
    deque<string> result;
    regex_split(std::back_inserter(result),s,expression);
    copy(result.begin(),result.end(),ostream_iterator<string>(cout,"\n"));
    int c;
    cin>>c;
    return 0;
    }
    設置BCB6 Project屬性的Lib Path和Include Path為你安裝boost的目錄,運行你會看到結果:
    index.html
    可以看到index.html已經從字符串中提出出來了,那么為什么會是這樣呢?
    代碼的核心部分是:
    regex expression("\\s+href\\s*=\\s*\"([^\"]*)\"",regbase::normal|regbase::icase);
    它用來設置如何匹配字符串,上面亂七八糟的字符串很難看懂,如果不了解正則表達式的書寫規則,上
    面代碼可以和天書媲美。
    regbase::normal|regbase::icase 是解析參數設置,具體可以參考boost幫助文檔。
    正則表達式的書寫規則
    具體的書寫規則,大家可以參看boost的文檔,我這里做一下簡要說明:
    . (dot)
    用來匹配任何一個字符,但不包括新行上的字符
    *
    閉包,任意有限次的自重復連接
    +
    有限次自重復連接,但至少出現一次
    {}
    指定可能的重復次數
    例如:
    ba* 匹配 b ba baa baaa等
    ba+ 匹配 ba baa baaaaaaaaa等
    ba{1,5} 匹配 ba baa baaa baaaa baaaaa
    \
    轉義字符,有很多用途,根據參數設置而變化,最常見的就是類似于c語言\的用法
    \s
    匹配空格
    \w
    匹配一個單詞
    \d
    匹配數字
    ()
    有兩種用法:
    1是合并的作用,例如(ab)*匹配ab abab ababab等
    2是確定匹配,也就是說在()中的字符將被最終拆解出來
    根據上面這張表,我們可以很容易知道前面的那段天書如何解釋。
    一個實際的例子
    前一段時間在CSDN上有一篇帖子,問題是有一種文件結構如(類似):
    @People{
    Age=19
    Speek=”Hay,{name},how are you”
    }
    問如何拆分字符串得到@后面的名字,=兩邊的屬性名和屬性值,引號里{}種的名字。
    解決這個問題用正則表達式再合適不過了。
    根據分析,我們可以這樣構造匹配規則:
    "@(.*?)\s*\\{" 匹配@開始的字符創,后面兩種類型如何構造匹配規則留給大家思考吧。
    這樣我們可以輕易拆解這個例子。

    性能分析
    通過上面的討論,大家已經了解到boost的強大威力,那個性能又如何呢?為此我們再實際來拆分一個
    復雜的html代碼,看看到底需要花費多少時間。
    為了節省篇幅,這里就不列出html代碼了,不過可以告訴大家,這是一個又Word生成的大小為186K
    的html文件,這個文件中用到了很多<table>標簽,所以我這里測試就來拆分所有<table>標簽的
    width屬性。測試代碼如下:
    #include<deque>
    #include<iostream>
    #include<algorithm>
    #include<boost/regex.hpp>
    #include<vcl.h>
    int main()
    {
     using namespace boost;
     using namespace std;
     TStringList* html=new TStringList();
     html->LoadFromFile("D:\\1.htm");
     regex expression("\\s+width=([^\"]*)\s+",regbase::normal|regbase::icase);
    DWORD start=GetTickCount();
     for(int n=0;n<html->Count;n++)
     {
        string s=html->Strings[n].c_str(); 
        deque<string> result;
        regex_split(std::back_inserter(result),s,expression);
    copy(result.begin(),result.end(),ostream_iterator<string>(cout,"\n"));
    result.clear();
    }
     start=GetTickCount()-start;
     delete html;
     cout<<start;
    int c;
     cin>>c;
     return 0;
    }
    輸出結果為671毫秒,拆分得到1072個width屬性值,我們可以看到boost的效率是非常高的,雖然與一些角本語言比起來解析速度還是慢,但已經可以滿足大多數編程要求了。另外作者的計算機配置并不是非常高,相信拿到現在任何一臺主流配置的計算機上都會優于作者的結果。
    結束語

    其實上面的強大威力只是boost的冰山一角,如果你不自己去體會,你很難想象到boost的強大威力。在boost里還有很多使用的庫,比如格式化輸出,字符串拆解,類型轉換等,這些庫使用起來也比較方便,大家可以自行參考boost文檔。在這些庫中還有兩個庫需要自行編譯,他們是Python和thread庫,而且這些庫的編譯需要專門的工具Jam,所以我們在編譯這些庫的時候還要編譯jam工具,而編譯jam工具也不是一件快樂的事情,麻煩同樣出現在如果你安裝了多個編譯器,如果讀者有興趣可以自己試一下。
    不過BCB6并不支持全部boost庫,從boost提供的編譯器支持表可以看到[2],BCB6還是有相當多的庫不支持的,支持最好的是gcc/g++的編譯器,但也不是全部支持。希望borland下一個將要發布的C++編譯器可以支持更多C++標準。
    [1] 其實還有其他類型的包,但在windows系統下,你最好下載zip包
    [2] Boost提供的編譯器支持表是針對BCB5的,對于BCB6的支持作者并沒有詳細測試,如果讀者有興趣可以自己測試boost附帶的測試代碼。

    posted @ 2008-12-07 21:22 john 閱讀(874) | 評論 (0)編輯 收藏

    RedHat LinuxAS4 cvs 服務器搭建步驟

    根據網上各種文檔整理而成.=號兩邊要空格的問題折磨了我好久.

     

    1:安裝

    先檢查是否安裝CVS包

    #>rpm -qa|grep cvs

    沒有安裝的話,用下面2種方法安裝

    (1):在安裝linux的時候可以選擇安裝CVS包
    (2):另外下載CVS RPM包 自行安裝

    2:建立cvs用戶和組

    #> groupadd cvs
    #> useradd -g cvs -G cvs –d /cvsroot cvsroot
    #> passwd cvsroot

    更改目錄屬性
    chmod –R 770 /cvsroot

    3:建立CVS服務

    #more /etc/services | grep cvspserver

    看看是否有
    cvspserver 2401/tcp #CVS client/server operations
    cvspserver 2401/udp #CVS client/server operations

    如果沒有需要到/etc/service文件中增加

    建立#vi /etc/xinet.d/cvspserver 文件內容如下

    service cvspserver
    {
    disable = no
    flags = REUSE
    socket_type = stream
    wait = no
    user = root
    server = /usr/bin/cvs
    server_args = -f --allow-root=/cvsroot pserver
    }

    該文件有特別要注意的地方,所有=號兩邊都需要空一個空格,除了"root=/cvsroot" 所有要空格的地方,不要多加空格.否則會有CVS服務不能啟動的問題

    切換到cvsroot用戶

    #cvs -d /cvsroot init

    然后重新啟動xinetd服務或者重啟動機器

    #service xinetd restart

    然后用

    #netstat -l | grep cvspserver
    or
    #netstat -l | grep 2401

    看是否有下面tcp 0 0 *:cvspserver *:* LISTEN

    說明已經正常啟動,沒有的話請重新檢查配置過程是否有錯誤或者遺漏。最后還必須檢查防火墻的設置,把2401端口打開。

    4:用戶管理

    CVS默認使用系統用戶登錄,所有系統用戶都可以登陸,但是這樣對系統不安全,我們需要獨立的用戶管理.CVS用戶名和密碼保存在CVSROOT目錄下的passwd文件中.格式

    用戶名:密碼:系統用戶

    #htpasswd passwd username

    用來設置用戶密碼并保存到passwd文件中.

    然后需要關閉系統用戶登陸使用cvs的權限,CVSROOT目錄下的config文件,把#SystemAuth=no的#去掉就可以了.

    測試登陸

    #cvs -d “:pserver:username@127.0.0.1:/cvsroot” login

    ok

     

    5 :源代碼倉庫的備份和移動
    基本上,CVS的源代碼倉庫沒有什么特別之處,完全可以用文件備份的方式進行備份。需要注意的只是,應該確認備份的過程中沒有用戶提交修改,具體的做法可以是停止CVS服務器或者使用鎖等等。恢復時只需要把這些文件按原來的目錄結構存放好,因為CVS的每一個模塊都是單獨的一個目錄,與其他模塊和目錄沒有任何瓜葛,相當方便。甚至只需要在倉庫中刪除一個目錄或者文件,便可以刪除該模塊的一些內容,不過并不建議這么做,使用CVS的刪除功能將會有一個歷史記錄,而對倉庫的直接刪除不留任何痕跡,這對項目管理是不利的。移動倉庫與備份相似,只需要把該模塊的目錄移動到新的路徑,便可以使用了。
    如果不幸在備份之后有過一些修改并且執行了提交,當服務器出現問題需要恢復源代碼倉庫時,開發者提交新的修改就會出現版本不一致的錯誤。此時只需要把CVS相關的目錄和文件刪除,即可把新的修改提交。

    6.更進一步的管理
    CVSROOT目錄下還有很多其他功能,其中最重要的就是modules文件。這個文件定義了源代碼庫的模塊,下面是一個例子:

    代碼:
    Linux    Linux
    Kernel   Linux/kernel


    這個文件的內容按行排列,每一行定義一個模塊,首先是模塊名,然后是模塊路徑,這是相對于CVS根目錄的路徑。它定義了兩個模塊,第一個是Linux模塊,它位于Linux目錄中,第二個是Kernel模塊,這是Linux模塊的子模塊。
    modules文件并非必須的,它的作用相當于一個索引,部分CVS客戶端軟件通過它可以快速找到相應的模塊,比如WinCVS。

    7.協同開發的問題
    默認方式下,CVS允許多個用戶編輯同一個文件,這對一個協作良好的團隊來說不會有什么問題,因為多個開發者同時修改同一個文件的同一部分是不正常的,這在項目管理中就應該避免,出現這種情況說明項目組內部沒有統一意見。而多個開發者修改文件的不同部分,CVS可以很好的管理。
    如果覺得這種方式難以控制,CVS也提供了解決辦法,可以使用cvs admin -l進行鎖定,這樣一個開發者正在做修改時CVS就不會允許其他用戶checkout。這里順便說明一下文件格式的問題,對于文本格式,CVS可以進行歷史記錄比較、版本合并等工作,而二進制文件不支持這個操作,比如word文檔、圖片等就應該以二進制方式提交。對于二進制方式,由于無法進行合并,在無法保證只有一個用戶修改文件的情況下,建議使用加鎖方式進行修改。必須注意的是,修改完畢記得解鎖。
    從1.6版本開始,CVS引入了監視的概念,這個功能可以讓用戶隨時了解當前誰在修改文件,并且CVS可以自動發送郵件給每一個監視的用戶告知最新的更新。

    8.建立多個源代碼倉庫
    如果需要管理多個開發組,而這些開發組之間不能互相訪問,可以有2個辦法:
    a.共用一個端口,需要修改cvspserver文件,給server_args指定多個源代碼路徑,即多個—allow-root參數。由于xinetd的server_args長度有限制,可以在cvspserver文件中把服務器的設置重定向到另外一個文件,如:

    代碼:
    server = /home/cvsroot/cvs.run


    然后創建/home/cvsroot/cvs.run文件,該文件必須可執行,內容格式為:

    代碼:
    #!/bin/bash
    /usr/bin/cvs -f \
    --allow-root=/home/cvsroot/src1 \
    --allow-root=/home/cvsroot/src2 \
    pserver


    注意此時源代碼倉庫不再是/home/cvsroot,進行初始化的時候要分別對這兩個倉庫路徑進行初始化,而不再對/home/cvsroot路徑進行初始化。
    b.采用不同的端口提供服務
    重復第2步和第3步,為不同的源代碼倉庫創建不同服務名的啟動腳本,并為這些服務名指定不同的端口,初始化時也必須分別進行初始化。
     
     

     

     

    posted @ 2008-05-25 02:04 john 閱讀(427) | 評論 (0)編輯 收藏

    Oracle 內存分配建議


     Oracle 內存分配建議
    關于SGA設置的一點總結
    本總結不針對特例,僅對服務器只存在OS + ORACLE 為例,如果存在其他應用請酌情考慮
    寫這個也是因為近來這種重復性的問題發生的太多所導致的

    首先不要迷信STS,SG,OCP,EXPERT 等給出的任何建議、內存百分比的說法
    基本掌握的原則是, data buffer 通常可以盡可能的大,shared_pool_size 要適度,log_buffer 通常大到幾百K到1M就差不多了

    設置之前,首先要明確2個問題
    1: 除去OS和一些其他開銷,能給ORACLE使用的內存有多大
    2:oracle是64bit or 32 bit,32bit 通常 SGA有 1.7G 的限制(某些OS的處理或者WINDOWS上有特定設定可以支持到2G以上甚至達到3.7G,本人無這方面經驗)

    下面是我的windows2000下的oracle :

    SQL> select * from v$version;

    BANNER
    ----------------------------------------------------------------
    Oracle8i Enterprise Edition Release 8.1.7.0.0 - Production
    PL/SQL Release 8.1.7.0.0 - Production
    CORE 8.1.7.0.0 Production
    TNS for 32-bit Windows: Version 8.1.7.0.0 - Production
    NLSRTL Version 3.4.1.0.0 - Production

    SQL>

    windows上存在32bit的限制,如AIX、HP UNIX 等有明確的64BIT OS and ORACLE的版本,32bit oracle可以裝在64bit os 上,64 bit oracle不能裝在32 bit OS上

    不管oracle是32 bit ORACLE還是 64 bit 的,假定應用存在沒有很好的使用bind var 的情況,也不能設置 shared_pool_size 過大,通常應該控制在200M--300M,如果是 ORACLE ERP 一類的使用了很多存儲過程函數、包 ,或者很大的系統,可以考慮增大shared_pool_size ,但是如果超過500M可能是危險的,達到1G可能會造成CPU的嚴重負擔,系統甚至癱瘓。所以shared_pool_size 如果超過300M還命中率不高,那么應該從應用上找原因而不是一味的增加內存,shared_pool_size 過大主要增加了管理負擔和latch 的開銷。

    log_buffer : 128K ---- 1M 之間通常問題不大,不應該太大

    large_pool_size :如果不設置MTS,通常在 RMAN 、OPQ 會使用到,但是在10M --- 50M 應該差不多了。假如設置 MTS,則由于 UGA 放到large_pool_size 的緣故,這個時候依據 session最大數量和 sort_ares_size 等參數設置,必須增大large_pool_size 的設置,可以考慮為 session * (sort_area_size + 2M)。這里要提醒一點,不是必須使用MTS,我們都不主張使用MTS,尤其同時在線用戶數小于500的情況下。

    java_pool_size : 若不使用java,給30M通常就夠了

    data buffer ,在做了前面的設置后,凡可以提供給oracle的內存,都應該給data buffer = (db_block_size * db_block_buffers)
    在9i 中可以是 db_cache_size

    還有2個重要參數我們需要注意

    sort_area_size and hash_area_size
    這兩個參數在非MTS下都是屬于PGA ,不屬于SGA,是為每個session單獨分配的,在我們的服務器上除了OS + SGA,一定要考慮這兩部分

    (****) : OS 使用內存+ SGA + session*(sort_area_size + hash_area_size + 2M) < 總物理RAM 為好


    這樣歸結過來,假定oracle是 32 bit ,服務器RAM大于2G ,注意你的PGA的情況,,則建議

    shared_pool_size + data buffer +large_pool_size + java_pool_size < 1.6G


    再具體化,注意滿足上面(****) 的原則的基礎上可以參考如下設置
    如果512M RAM
    建議 shared_pool_size = 50M, data buffer = 200M

    如果1G RAM
    shared_pool_size = 100M , data buffer = 500M

    如果2G
    shared_pool_size = 150M ,data buffer = 1.2G

    物理內存再大已經跟參數沒有關系了


    假定64 bit ORACLE

    內存4G
    shared_pool_size = 200M , data buffer = 2.5G

    內存8G
    shared_pool_size = 300M , data buffer = 5G

    內存 12G
    shared_pool_size = 300M-----800M , data buffer = 8G



    以上僅為參考值,不同系統可能差異比較大,需要根據具體情況調整。建議在設置參數的同時,init中使用 lock_sga ,在不同的平臺上可能有不同的方式,使得SGA鎖定在物理內存中而不被放入 SWAP 中,這樣對效率有好處


    關于內存的設置,要再進行細致的調整,起的作用不大,但可根據statspack信息和v$system_event,v$sysstat,v$sesstat,v$latch 等view信息來考慮微調

    posted @ 2008-01-28 23:58 john 閱讀(794) | 評論 (0)編輯 收藏

    Oracle 回滾段空間回收步驟

         摘要:   是誰"偷偷的"用了那么多空間呢(本來有幾十個G的Free磁盤空間的)? 檢查數據庫表空間占用空間情況: SQL> select tablespace_name,sum(bytes)/1024/1024/1024 GB  2 from dba...  閱讀全文

    posted @ 2007-12-27 00:50 john 閱讀(2252) | 評論 (1)編輯 收藏

    常用的MQ命令

    最近在配置MQ,記下了一些常用的MQ命令,如下:

    創建隊列管理器
    crtmqm –q QMgrName
    -q是指創建缺省的隊列管理器

    刪除隊列管理器
    dltmqm QmgrName

    啟動隊列管理器
    strmqm QmgrName
    如果是啟動默認的隊列管理器,可以不帶其名字

    停止隊列管理器
    endmqm QmgrName 受控停止

    endmqm –i QmgrName 立即停止

    endmqm –p QmgrName 強制停止

    顯示隊列管理器
    dspmq –m QmgrName

    運行MQ命令
    runmqsc QmgrName
    如果是默認隊列管理器,可以不帶其名字

    往隊列中放消息
    amqsput QName QmgrName
    如果隊列是默認隊列管理器中的隊列,可以不帶其隊列管理器的名字

    從隊列中取出消息
    amqsget QName QmgrName
    如果隊列是默認隊列管理器中的隊列,可以不帶其隊列管理器的名字

    啟動通道
    runmqchl –c ChlName –m QmgrName

    啟動偵聽
    runmqlsr –t TYPE –p PORT –m QMgrName

    停止偵聽
    endmqlsr -m QmgrName

    下面是在MQ環境中可以執行的MQ命令(即在runmqsc環境下可以敲的命令)

    定義持久信隊列
    DEFINE QLOCAL(QNAME) DEFPSIST(YES) REPLACE

    設定隊列管理器的持久信隊列
    ALTER QMGR DEADQ(QNAME)

    定義本地隊列
    DEFINE QL(QNAME) REPLACE

    定義別名隊列
    DEFINE QALIAS(QALIASNAME) TARGQ(QNAME)

    遠程隊列定義
    DEFINE QREMOTE(QRNAME) +
    RNAME(AAA) RQMNAME(QMGRNAME) +
    XMITQ(QTNAME)

    定義模型隊列
    DEFINE QMODEL(QNAME) DEFTYPE(TEMPDYN)

    定義本地傳輸隊列
    DEFINE QLOCAL(QTNAME) USAGE(XMITQ) DEFPSIST(YES) +
    INITQ(SYSTEM.CHANNEL.INITQ)+
    PROCESS(PROCESSNAME) REPLACE

    創建進程定義
    DEFINE PROCESS(PRONAME) +
    DESCR(‘STRING’)+
    APPLTYPE(WINDOWSNT)+
    APPLICID(’ runmqchl -c SDR_TEST -m QM_ TEST’)
    其中APPLTYPE的值可以是:CICS、UNIX、WINDOWS、WINDOWSNT等

    創建發送方通道
    DEFINE CHANNEL(SDRNAME) CHLTYPE(SDR)+
    CONNAME(‘100.100.100.215(1418)’) XMITQ(QTNAME) REPLACE
    其中CHLTYPE可以是:SDR、SVR、RCVR、RQSTR、CLNTCONN、SVRCONN、CLUSSDR和CLUSRCVR。

    創建接收方通道
    DEFINE CHANNEL(SDR_ TEST) CHLTYPE(RCVR) REPLACE

    創建服務器連接通道
    DEFINE CHANNEL(SVRCONNNAME) CHLTYPE(SVRCONN) REPLACE

    顯示隊列的所有屬性
    DISPLAY QUEUE(QNAME) [ALL]

    顯示隊列的所選屬性
    DISPLAY QUEUE(QNAME) DESCR GET PUT
    DISPLAY QUEUE(QNAME)MAXDEPTH CURDEPTH

    顯示隊列管理器的所有屬性
    DISPLAY QMGR [ALL]

    顯示進程定義
    DISPLAY PROCESS(PRONAME)

    更改屬性
    ALTER QMGR DESCR(‘NEW DESCRIPTION’)
    ALTER QLOCAL(QNAME) PUT(DISABLED)
    ALTER QALIAS(QNAME) TARGQ(TARGQNAME)

    刪除隊列
    DELETE QLOCAL(QNAME)
    DELETE QREMOTE(QRNAME)

    清除隊列中的所有消息
    CLEAR QLOCAL(QNAME)

    以下是一些高級配置的命令:

    amqmcert                  配置SSL證書

    amqmdain                配置windows上的MQ服務

    crtmqcvx                    轉換數據

    dmpmqaut                轉儲對象權限管理

    dmpmqlog                轉儲日志管理

    dspmq                         顯示隊列管理器

    dspmqaut                  顯示打開對象的權限

    dmpmqcap               顯示處理程序容量和處理程序數

    dspmqcsv                 顯示命令服務器狀態

    dspmqfls                   顯示文件名

    dspmqtrc                   跟蹤MQ輸出(HP-UNIX LINUX Solaris)

    dspmqrtn                   顯示事務的詳細信息

    endmqcsv                 停止隊列管理器上的命令服務器

    strmqcsv                    啟動隊列管理器上的命令服務器

    endmqtrc                   停止跟蹤

    rcdmqimg                  向日志寫對象的映像

    rcmqobj                      根據日志中的映像重新創建一個對象

    rsvmqtrn                     提交或逆序恢復事務

     


    posted @ 2007-12-26 17:26 john 閱讀(2589) | 評論 (0)編輯 收藏

    BCB UTF-8 格式轉換

    如果是字串轉換.BCB有多個方法(如TStringConverter,或API的 WideCharToMultiByte/MultiByteToWideChar,VCL的WideCharToString/StringToWideChar等)
    當然,BCB本身就支持三種字串,前兩種可自動轉,后一種有函數:
    String x; //GBK
    WideString y; //unicode
    UTF8String z; //utf8

    x=y; //自動
    y=x; //自動
    z=AnsiToUtf8(x);
    x=Utf8ToAnsi(z);

    posted @ 2007-11-22 18:11 john 閱讀(2681) | 評論 (1)編輯 收藏

    Oracle安裝的一些問題收集

         摘要: 在安裝過程中出現的一些問題的解決辦法。值得收藏與學習。比如在安裝的時候如果有中文的路徑則會出現類似這樣的提示:加載數據庫時出錯:areasQueries Oracle的系統要求 企業版:CPU 最低PENTIUM 200M 推薦 PENTIUMIII 1G以上     內存 最低128M 推薦 512M     硬盤空間 系統盤140M 安裝盤4.5G(FAT32)或2.75G(...  閱讀全文

    posted @ 2007-10-24 20:50 john 閱讀(1829) | 評論 (0)編輯 收藏

    東京愛情故事?

    在經歷了一段時間的起起落落以后,開始靜下心來回顧近4年的往事,也想到了把東京愛情故事下載了下來看。用了1天時間把這部電視看完了。莉香的笑容確實讓人感到陽光燦爛;我覺得她最大的錯誤,是喜歡了本來就不屬于她的“丸子”。從故事一開始,就可以知道,完治的心留在了同學“里美”那里了,對于完治來說,莉香的出現,只是生命中的一個小小插曲。

    posted @ 2007-07-23 23:08 john 閱讀(272) | 評論 (0)編輯 收藏

    關于Bill Gates的一些評論,我喜歡

    比爾~蓋茨最聰明的地方不是他做了什么,而是他沒做什么。他可以做許許多多的事情,卻只專注在自己的操作系統,軟件研發二不被市場中別的誘惑吸引。

    做人要謙卑,做事要學會不斷找問題--比爾·蓋茨
    在真理面前的謙卑,是比爾·蓋茨一種內心態度,遠比外面的風光無限、備受世人崇敬更重要。
    有了在真理面前的謙卑,就可以在這個浮躁的世界中保持一顆安靜的心靈,有更大的創造力和影響力。

    posted @ 2007-07-23 22:55 john 閱讀(312) | 評論 (0)編輯 收藏

    Linux系統環境下的Socket編程詳細解析

    Linux系統環境下的Socket編程詳細解析

    什么是Socket

      Socket接口是TCP/IP網絡的API,Socket接口定義了許多函數或例程,程序員可以用它們來開發TCP/IP網絡上的應用程序。要學Internet上的TCP/IP網絡編程,必須理解Socket接口。

      Socket接口設計者最先是將接口放在Unix操作系統里面的。如果了解Unix系統的輸入和輸出的話,就很容易了解Socket了。網絡的Socket數據傳輸是一種特殊的I/O,Socket也是一種文件描述符。Socket也具有一個類似于打開文件的函數調用Socket(),該函數返回一個整型的Socket描述符,隨后的連接建立、數據傳輸等操作都是通過該Socket實現的。常用的Socket類型有兩種:流式Socket(SOCK_STREAM)和數據報式Socket(SOCK_DGRAM)。流式是一種面向連接的Socket,針對于面向連接的TCP服務應用;數據報式Socket是一種無連接的Socket,對應于無連接的UDP服務應用。

      Socket建立

      為了建立Socket,程序可以調用Socket函數,該函數返回一個類似于文件描述符的句柄。socket函數原型為:

      int socket(int domain, int type, int protocol);

      domain指明所使用的協議族,通常為PF_INET,表示互聯網協議族(TCP/IP協議族);type參數指定socket的類型:SOCK_STREAM 或SOCK_DGRAM,Socket接口還定義了原始Socket(SOCK_RAW),允許程序使用低層協議;protocol通常賦值"0"。Socket()調用返回一個整型socket描述符,你可以在后面的調用使用它。

      Socket描述符是一個指向內部數據結構的指針,它指向描述符表入口。調用Socket函數時,socket執行體將建立一個Socket,實際上"建立一個Socket"意味著為一個Socket數據結構分配存儲空間。Socket執行體為你管理描述符表。

      兩個網絡程序之間的一個網絡連接包括五種信息:通信協議、本地協議地址、本地主機端口、遠端主機地址和遠端協議端口。Socket數據結構中包含這五種信息。

      Socket配置

      通過socket調用返回一個socket描述符后,在使用socket進行網絡傳輸以前,必須配置該socket。面向連接的socket客戶端通過調用Connect函數在socket數據結構中保存本地和遠端信息。無連接socket的客戶端和服務端以及面向連接socket的服務端通過調用bind函數來配置本地信息。
    Bind函數將socket與本機上的一個端口相關聯,隨后你就可以在該端口監聽服務請求。Bind函數原型為:

      

    int bind(int sockfd,struct sockaddr *my_addr, int addrlen); 
      Sockfd是調用socket函數返回的socket描述符, my_addr是一個指向包含有本機IP地址及端口號等信息的sockaddr類型的指針; addrlen常被設置為sizeof(struct sockaddr)。
      struct sockaddr結構類型是用來保存socket信息的:
      struct sockaddr {
       unsigned short sa_family; /* 地址族, AF_xxx */
    char sa_data[14]; /* 14 字節的協議地址 */
    };
      sa_family一般為AF_INET,代表Internet(TCP/IP)地址族;sa_data
    則包含該socket的IP地址和端口號。
      另外還有一種結構類型:
      struct sockaddr_in {
       short int sin_family; /* 地址族 */
       unsigned short int sin_port; /* 端口號 */
       struct in_addr sin_addr; /* IP地址 */
       unsigned char sin_zero[8]; /* 填充0 以保持與struct sockaddr同樣大小 */
      };

     

      這個結構更方便使用。sin_zero用來將sockaddr_in結構填充到與struct sockaddr同樣的長度,可以用bzero()或memset()函數將其置為零。指向sockaddr_in 的指針和指向sockaddr的指針可以相互轉換,這意味著如果一個函數所需參數類型是sockaddr時,你可以在函數調用的時候將一個指向sockaddr_in的指針轉換為指向sockaddr的指針;或者相反。

      使用bind函數時,可以用下面的賦值實現自動獲得本機IP地址和隨機獲取一個沒有被占用的端口號:

      my_addr.sin_port = 0; /* 系統隨機選擇一個未被使用的端口號 */
      my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本機IP地址 */
    通過將my_addr.sin_port置為0,函數會自動為你選擇一個未占用的端口來使用。同樣,通過將my_addr.sin_addr.s_addr置為INADDR_ANY,系統會自動填入本機IP地址。

      注意在使用bind函數是需要將sin_port和sin_addr轉換成為網絡字節優先順序;而sin_addr則不需要轉換。

      計算機數據存儲有兩種字節優先順序:高位字節優先和低位字節優先。Internet上數據以高位字節優先順序在網絡上傳輸,所以對于在內部是以低位字節優先方式存儲數據的機器,在Internet上傳輸數據時就需要進行轉換,否則就會出現數據不一致。

      下面是幾個字節順序轉換函數:

    ·htonl():把32位值從主機字節序轉換成網絡字節序 
    ·htons():把16位值從主機字節序轉換成網絡字節序
    ·ntohl():把32位值從網絡字節序轉換成主機字節序
    ·ntohs():把16位值從網絡字節序轉換成主機字節序

     

      Bind()函數在成功被調用時返回0;出現錯誤時返回"-1"并將errno置為相應的錯誤號。需要注意的是,在調用bind函數時一般不要將端口號置為小于1024的值,因為1到1024是保留端口號,你可以選擇大于1024中的任何一個沒有被占用的端口號。

    連接建立

     

      面向連接的客戶程序使用Connect函數來配置socket并與遠端服務器建立一個TCP連接,其函數原型為:

      int connect(int sockfd, struct sockaddr *serv_addr,int addrlen);
    Sockfd是socket函數返回的socket描述符;serv_addr是包含遠端主機IP地址和端口號的指針;addrlen是遠端地質結構的長度。Connect函數在出現錯誤時返回-1,并且設置errno為相應的錯誤碼。進行客戶端程序設計無須調用bind(),因為這種情況下只需知道目的機器的IP地址,而客戶通過哪個端口與服務器建立連接并不需要關心,socket執行體為你的程序自動選擇一個未被占用的端口,并通知你的程序數據什么時候到打斷口。

      Connect函數啟動和遠端主機的直接連接。只有面向連接的客戶程序使用socket時才需要將此socket與遠端主機相連。無連接協議從不建立直接連接。面向連接的服務器也從不啟動一個連接,它只是被動的在協議端口監聽客戶的請求。

      Listen函數使socket處于被動的監聽模式,并為該socket建立一個輸入數據隊列,將到達的服務請求保存在此隊列中,直到程序處理它們。

      int listen(int sockfd, int backlog);

      Sockfd是Socket系統調用返回的socket 描述符;backlog指定在請求隊列中允許的最大請求數,進入的連接請求將在隊列中等待accept()它們(參考下文)。Backlog對隊列中等待服務的請求的數目進行了限制,大多數系統缺省值為20。如果一個服務請求到來時,輸入隊列已滿,該socket將拒絕連接請求,客戶將收到一個出錯信息。

      當出現錯誤時listen函數返回-1,并置相應的errno錯誤碼。

      accept()函數讓服務器接收客戶的連接請求。在建立好輸入隊列后,服務器就調用accept函數,然后睡眠并等待客戶的連接請求。

      int accept(int sockfd, void *addr, int *addrlen);

      sockfd是被監聽的socket描述符,addr通常是一個指向sockaddr_in變量的指針,該變量用來存放提出連接請求服務的主機的信息(某臺主機從某個端口發出該請求);addrten通常為一個指向值為sizeof(struct sockaddr_in)的整型指針變量。出現錯誤時accept函數返回-1并置相應的errno值。

      首先,當accept函數監視的socket收到連接請求時,socket執行體將建立一個新的socket,執行體將這個新socket和請求連接進程的地址聯系起來,收到服務請求的初始socket仍可以繼續在以前的 socket上監聽,同時可以在新的socket描述符上進行數據傳輸操作。

      數據傳輸

      Send()和recv()這兩個函數用于面向連接的socket上進行數據傳輸。

      Send()函數原型為:

      int send(int sockfd, const void *msg, int len, int flags);
    Sockfd是你想用來傳輸數據的socket描述符;msg是一個指向要發送數據的指針;Len是以字節為單位的數據的長度;flags一般情況下置為0(關于該參數的用法可參照man手冊)。

      Send()函數返回實際上發送出的字節數,可能會少于你希望發送的數據。在程序中應該將send()的返回值與欲發送的字節數進行比較。當send()返回值與len不匹配時,應該對這種情況進行處理。
    char *msg = "Hello!";
    int len, bytes_sent;
    ……
    len = strlen(msg);
    bytes_sent = send(sockfd, msg,len,0);
    ……
      recv()函數原型為:

      int recv(int sockfd,void *buf,int len,unsigned int flags);

      Sockfd是接受數據的socket描述符;buf 是存放接收數據的緩沖區;len是緩沖的長度。Flags也被置為0。Recv()返回實際上接收的字節數,當出現錯誤時,返回-1并置相應的errno值。

      Sendto()和recvfrom()用于在無連接的數據報socket方式下進行數據傳輸。由于本地socket并沒有與遠端機器建立連接,所以在發送數據時應指明目的地址。
      Sendto()函數原型為:
      int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);

      該函數比send()函數多了兩個參數,to表示目地機的IP地址和端口號信息,而tolen常常被賦值為sizeof (struct sockaddr)。Sendto 函數也返回實際發送的數據字節長度或在出現發送錯誤時返回-1。

      Recvfrom()函數原型為:

      int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);

      from是一個struct sockaddr類型的變量,該變量保存源機的IP地址及端口號。fromlen常置為sizeof (struct sockaddr)。當recvfrom()返回時,fromlen包含實際存入from中的數據字節數。Recvfrom()函數返回接收到的字節數或當出現錯誤時返回

      1,并置相應的errno。

      如果你對數據報socket調用了connect()函數時,你也可以利用send()和recv()進行數據傳輸,但該socket仍然是數據報socket,并且利用傳輸層的UDP服務。但在發送或接收數據報時,內核會自動為之加上目地和源地址信息。

      結束傳輸

      當所有的數據操作結束以后,你可以調用close()函數來釋放該socket,從而停止在該socket上的任何數據操作:

      close(sockfd);

      你也可以調用shutdown()函數來關閉該socket。該函數允許你只停止在某個方向上的數據傳輸,而一個方向上的數據傳輸繼續進行。如你可以關閉某socket的寫操作而允許繼續在該socket上接受數據,直至讀入所有數據。

      int shutdown(int sockfd,int how);

      Sockfd是需要關閉的socket的描述符。參數 how允許為shutdown操作選擇以下幾種方式:
    ·0-------不允許繼續接收數據
    ·1-------不允許繼續發送數據
    ·2-------不允許繼續發送和接收數據,
    ·均為允許則調用close ()

      shutdown在操作成功時返回0,在出現錯誤時返回-1并置相應errno。

     面向連接的Socket實例

     

      代碼實例中的服務器通過socket連接向客戶端發送字符串"Hello, you are connected!"。只要在服務器上運行該服務器軟件,在客戶端運行客戶軟件,客戶端就會收到該字符串。

      該服務器軟件代碼如下:

    #include  
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #define SERVPORT 3333 /*服務器監聽端口號 */
    #define BACKLOG 10 /* 最大同時連接請求數 */
    main()
    {
    int sockfd,client_fd; /*sock_fd:監聽socket;client_fd:數據傳輸socket */
     struct sockaddr_in my_addr; /* 本機地址信息 */
     struct sockaddr_in remote_addr; /* 客戶端地址信息 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      perror("socket創建出錯!"); exit(1);
    }
    my_addr.sin_family=AF_INET;
     my_addr.sin_port=htons(SERVPORT);
     my_addr.sin_addr.s_addr = INADDR_ANY;
    bzero(&(my_addr.sin_zero),8);
     if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \
       == -1) {
    perror("bind出錯!");
    exit(1);
    }
     if (listen(sockfd, BACKLOG) == -1) {
    perror("listen出錯!");
    exit(1);
    }
    while(1) {
      sin_size = sizeof(struct sockaddr_in);
      if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, \
      &sin_size)) == -1) {
    perror("accept出錯");
    continue;
    }
      printf("received a connection from %s\n", inet_ntoa(remote_addr.sin_addr));
      if (!fork()) { /* 子進程代碼段 */
       if (send(client_fd, "Hello, you are connected!\n", 26, 0) == -1)
       perror("send出錯!");
    close(client_fd);
    exit(0);
    }
      close(client_fd);
      }
     }
    }

     

      服務器的工作流程是這樣的:首先調用socket函數創建一個Socket,然后調用bind函數將其與本機地址以及一個本地端口號綁定,然后調用listen在相應的socket上監聽,當accpet接收到一個連接服務請求時,將生成一個新的socket。服務器顯示該客戶機的IP地址,并通過新的socket向客戶端發送字符串"Hello,you are connected!"。最后關閉該socket。

      代碼實例中的fork()函數生成一個子進程來處理數據傳輸部分,fork()語句對于子進程返回的值為0。所以包含fork函數的if語句是子進程代碼部分,它與if語句后面的父進程代碼部分是并發執行的。

      客戶端程序代碼如下:

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #define SERVPORT 3333
    #define MAXDATASIZE 100 /*每次最大數據傳輸量 */
    main(int argc, char *argv[]){
     int sockfd, recvbytes;
     char buf[MAXDATASIZE];
     struct hostent *host;
     struct sockaddr_in serv_addr;
     if (argc < 2) {
    fprintf(stderr,"Please enter the server's hostname!\n");
    exit(1);
    }
     if((host=gethostbyname(argv[1]))==NULL) {
    herror("gethostbyname出錯!");
    exit(1);
    }
     if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
    perror("socket創建出錯!");
    exit(1);
    }
     serv_addr.sin_family=AF_INET;
     serv_addr.sin_port=htons(SERVPORT);
     serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
     bzero(&(serv_addr.sin_zero),8);
     if (connect(sockfd, (struct sockaddr *)&serv_addr, \
       sizeof(struct sockaddr)) == -1) {
    perror("connect出錯!");
    exit(1);
    }
     if ((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) ==-1) {
    perror("recv出錯!");
    exit(1);
    }
     buf[recvbytes] = '\0';
     printf("Received: %s",buf);
     close(sockfd);
    }
    客戶端程序首先通過服務器域名獲得服務器的IP地址,然后創建一個socket,調用connect函數與服務器建立連接,連接成功之后接收從服務器發送過來的數據,最后關閉socket。

      函數gethostbyname()是完成域名轉換的。由于IP地址難以記憶和讀寫,所以為了方便,人們常常用域名來表示主機,這就需要進行域名和IP地址的轉換。函數原型為:


      struct hostent *gethostbyname(const char *name); 
      函數返回為hosten的結構類型,它的定義如下:
      struct hostent {
      char *h_name; /* 主機的官方域名 */
       char **h_aliases; /* 一個以NULL結尾的主機別名數組 */
       int h_addrtype; /* 返回的地址類型,在Internet環境下為AF-INET */
      int h_length; /* 地址的字節長度 */
       char **h_addr_list; /* 一個以0結尾的數組,包含該主機的所有地址*/
      };
      #define h_addr h_addr_list[0] /*在h-addr-list中的第一個地址*/

     

      當 gethostname()調用成功時,返回指向struct hosten的指針,當調用失敗時返回-1。當調用gethostbyname時,你不能使用perror()函數來輸出錯誤信息,而應該使用herror()函數來輸出。

      無連接的客戶/服務器程序的在原理上和連接的客戶/服務器是一樣的,兩者的區別在于無連接的客戶/服務器中的客戶一般不需要建立連接,而且在發送接收數據時,需要指定遠端機的地址。

      阻塞和非阻塞

      阻塞函數在完成其指定的任務以前不允許程序調用另一個函數。例如,程序執行一個讀數據的函數調用時,在此函數完成讀操作以前將不會執行下一程序語句。當服務器運行到accept語句時,而沒有客戶連接服務請求到來,服務器就會停止在accept語句上等待連接服務請求的到來。這種情況稱為阻塞(blocking)。而非阻塞操作則可以立即完成。比如,如果你希望服務器僅僅注意檢查是否有客戶在等待連接,有就接受連接,否則就繼續做其他事情,則可以通過將Socket設置為非阻塞方式來實現。非阻塞socket在沒有客戶在等待時就使accept調用立即返回。
      #include
      #include
      ……
    sockfd = socket(AF_INET,SOCK_STREAM,0);
    fcntl(sockfd,F_SETFL,O_NONBLOCK);
    ……

      通過設置socket為非阻塞方式,可以實現"輪詢"若干Socket。當企圖從一個沒有數據等待處理的非阻塞Socket讀入數據時,函數將立即返回,返回值為-1,并置errno值為EWOULDBLOCK。但是這種"輪詢"會使CPU處于忙等待方式,從而降低性能,浪費系統資源。而調用select()會有效地解決這個問題,它允許你把進程本身掛起來,而同時使系統內核監聽所要求的一組文件描述符的任何活動,只要確認在任何被監控的文件描述符上出現活動,select()調用將返回指示該文件描述符已準備好的信息,從而實現了為進程選出隨機的變化,而不必由進程本身對輸入進行測試而浪費CPU開銷。Select函數原型為:
    int select(int numfds,fd_set *readfds,fd_set *writefds,
    fd_set *exceptfds,struct timeval *timeout);

      其中readfds、writefds、exceptfds分別是被select()監視的讀、寫和異常處理的文件描述符集合。如果你希望確定是否可以從標準輸入和某個socket描述符讀取數據,你只需要將標準輸入的文件描述符0和相應的sockdtfd加入到readfds集合中;numfds的值是需要檢查的號碼最高的文件描述符加1,這個例子中numfds的值應為sockfd+1;當select返回時,readfds將被修改,指示某個文件描述符已經準備被讀取,你可以通過FD_ISSSET()來測試。為了實現fd_set中對應的文件描述符的設置、復位和測試,它提供了一組宏:
      FD_ZERO(fd_set *set)----清除一個文件描述符集;
      FD_SET(int fd,fd_set *set)----將一個文件描述符加入文件描述符集中;
      FD_CLR(int fd,fd_set *set)----將一個文件描述符從文件描述符集中清除;
      FD_ISSET(int fd,fd_set *set)----試判斷是否文件描述符被置位。
      Timeout參數是一個指向struct timeval類型的指針,它可以使select()在等待timeout長時間后沒有文件描述符準備好即返回。struct timeval數據結構為:
      struct timeval {
       int tv_sec; /* seconds */
       int tv_usec; /* microseconds */ };

      POP3客戶端實例

      下面的代碼實例基于POP3的客戶協議,與郵件服務器連接并取回指定用戶帳號的郵件。與郵件服務器交互的命令存儲在字符串數組POPMessage中,程序通過一個do-while循環依次發送這些命令。

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #define POP3SERVPORT 110
    #define MAXDATASIZE 4096

     

    main(int argc, char *argv[]){
    int sockfd;
    struct hostent *host;
    struct sockaddr_in serv_addr;
    char *POPMessage[]={
    "USER userid\r\n",
    "PASS password\r\n",
    "STAT\r\n",
    "LIST\r\n",
    "RETR 1\r\n",
    "DELE 1\r\n",
    "QUIT\r\n",
    NULL
    };
    int iLength;
    int iMsg=0;
    int iEnd=0;
    char buf[MAXDATASIZE];

    if((host=gethostbyname("your.server"))==NULL) {
    perror("gethostbyname error");
    exit(1);
    }
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
    perror("socket error");
    exit(1);
    }
    serv_addr.sin_family=AF_INET;
    serv_addr.sin_port=htons(POP3SERVPORT);
    serv_addr.sin_addr = *((struct in_addr *)host->h_addr);
    bzero(&(serv_addr.sin_zero),8);
    if (connect(sockfd, (struct sockaddr *)&serv_addr,sizeof(struct sockaddr))==-1){
    perror("connect error");
    exit(1);
    }

    do {
    send(sockfd,POPMessage[iMsg],strlen(POPMessage[iMsg]),0);
    printf("have sent: %s",POPMessage[iMsg]);

    iLength=recv(sockfd,buf+iEnd,sizeof(buf)-iEnd,0);
    iEnd+=iLength;
    buf[iEnd]='\0';
    printf("received: %s,%d\n",buf,iMsg);

    iMsg++;
    } while (POPMessage[iMsg]);

    close(sockfd);
    }

    posted @ 2007-07-23 22:45 john 閱讀(655) | 評論 (0)編輯 收藏

    ORA-27121 錯誤,找了好半天:(

    遇到 ORA-27121 錯誤
    ORA-01034: ORACLE not available
    ORA-27121: unable to determine size of shared memory segment
    Linux Error: 13: Permission denied

    主要是因為oracle安裝程序沒有給oracle這個可執行程序設置正確的setuid。這樣設置一下:

    $ cd $ORACLE_HOME/bin
    $ chmod 6751 oracle

    結果類似這樣就行了。

    $ ls -l $ORACLE_HOME/bin/oracle
    -rwsr-s--x 1 oracle oinstall 23352783 Aug 14 2001 /home/oracle/app/oracle/product/8.1.6/bin/oracle



    這個錯誤的典型現象:使用oracle用戶一切正常,但是在使用其它用戶時,使用sqlplus無法登錄,報告上面的錯誤!

    posted @ 2007-07-17 17:03 john 閱讀(2110) | 評論 (1)編輯 收藏

    Oracle 的Trigger 中不能操作基表(轉)

    在將SYBASE的Trigger移植到ORACLE的時候發現一個問題,

    就是在一張表的Trigger中不能含有操作該基表的SQL,

    例如STOCKINFO的Trigger里不有操作STOCKINFO的SQL。

    那加權平均價如何取呢?

    現在只能在原平均價的基礎再與新價進行加權平均,結果是一樣的。

    注意:

    AFTER UPDATE的Trigger不能操作基表,只有在BEFORE INSERT的Trigger里才能操作基表。

    BEFORE INSERT的Trigger只有用INSERT INTO T1(COL1) VALUES('1');才有效,

    INSERT INTO T1(COL1) SELECT '1' FROM DUAL;也是無效的。

    例如:

    SQL> insert into t1 values (1,'a'); --先插入一條數據,避免ORA-01403: no data found 錯誤。
    1 row inserted
    SQL> commit;

    SQL> create or replace trigger tri_t1
    2 before insert on t1 for each row
    3 declare
    4 cvar varchar2(10);
    5 begin
    6 select 'Y' into cvar from t1 WHERE ROWNUM=1;
    7 end;
    8 /
    Trigger created

    SQL> insert into t1 values (2,'b'); -- insert into ... values 沒有問題
    1 row inserted

    SQL> insert into t1 select '3','c' from dual; -- insert into ... select .. from 報錯
    ORA-04091: table TEST.T1 is mutating, trigger/function may not see it
    ORA-06512: at "TEST.TRI_T1", line 4
    ORA-04088: error during execution of trigger 'TEST.TRI_T1'

     并且:old和:new只有在行級(for each row)的Trigger有效。

    網上原文:

    ORA-04091與 table mutating

    近日解決了一個trigger中報ORA-04091錯誤的問題,補了關于Oracle table mutating的一課:

    mutating table 是指一個當前正在被update,delete,insert語句修改的表,如果在一個行級別的trigger中讀取或修改一個mutating table,則往往會遇到ORA-04091錯誤.例如,如果在trigger中使用了select或dml 語句訪問trigger所在的表,則就會收到這個錯誤。

    然而,Oracle8i和9i文檔中都沒有解釋清楚before和after 類型的 row trigger 在對待兩種不同的insert語句(insert into ... values ... 與 insert into ... select ...)時的差別:

    1、對于after 類型的 for each row 級別的triggers,不論哪種insert語句觸發了trigger,都不允許在 trigger 中訪問本trigger所依賴的table的,測試如下:
    SQL> create table t1 ( c1 number,c2 varchar2(10));
    Table created
    SQL> create or replace trigger tri_t1
    2 after insert on t1 for each row
    3 declare
    4 cvar varchar2(10);
    5 begin
    6 select 'Y' into cvar from t1 WHERE ROWNUM=1; --這里訪問了trigger 本表
    7 end;
    8 /
    Trigger created

    SQL> insert into t1 values (1,'a');
    ORA-04091: table TEST.T1 is mutating, trigger/function may not see it
    ORA-06512: at "TEST.TRI_T1", line 4
    ORA-04088: error during execution of trigger 'TES.TRI_T1'

    SQL> insert into t1 select '1','a' from dual;
    ORA-04091: table TEST.T1 is mutating, trigger/function may not see it
    ORA-06512: at "TEST.TRI_T1", line 4
    ORA-04088: error during execution of trigger 'TEST.TRI_T1'

    2、對于before 類型的 for each row 級別的triggers,如果使用 insert into ... values 語句觸發此trigger ,則在trigger 中訪問本table沒有問題;
    但如果使用 insert into select .. from 語句觸發此trigger ,則在trigger 中訪問本table就報ora-04091錯誤;
    只有在Oracle 7標準的開發文檔中有這樣的說明:
    From the Application Developers Guide
    "There is an exception to this restriction;
    For single row INSERTs, constraining tables are mutating for
    AFTER row triggers, but not for BEFORE row triggers.
    INSERT statements that involve more than 1 row are not considered
    single row inserts."
    "INSERT INTO <table_name> SELECT ..." are not considered single row
    inserts, even if they only result in 1 row being inserted.

    測試如下:
    SQL> drop trigger tri_t1;
    Trigger dropped

    SQL> insert into t1 values (1,'a'); --先插入一條數據,避免ORA-01403: no data found 錯誤。
    1 row inserted
    SQL> commit;

    SQL> create or replace trigger tri_t1
    2 before insert on t1 for each row
    3 declare
    4 cvar varchar2(10);
    5 begin
    6 select 'Y' into cvar from t1 WHERE ROWNUM=1;
    7 end;
    8 /
    Trigger created

    SQL> insert into t1 values (2,'b'); -- insert into ... values 沒有問題
    1 row inserted

    SQL> insert into t1 select '3','c' from dual; -- insert into ... select .. from 報錯
    ORA-04091: table TEST.T1 is mutating, trigger/function may not see it
    ORA-06512: at "TEST.TRI_T1", line 4
    ORA-04088: error during execution of trigger 'TEST.TRI_T1'

    我們的開發人員因為不知道這個特別情況,近日在修改一個存儲過程時候,將原來的insert values 寫法改成了insert select 寫法,而trigger 又是before類型的,導致出現了ORA-04091錯誤,搞得分析了好久也沒有頭緒。

    其實,在metalink中有一篇note說到了:

    文檔 ID: 注釋:132569.1
    主題: ORA-4091 on BEFORE ROW TRIGGER with INSERT statement
    類型: PROBLEM
    狀態: PUBLISHED
    內容類型: TEXT/X-HTML
    創建日期: 16-JAN-2001
    上次修訂日期: 09-AUG-2004

    Problem Description
    -------------------

    You want to do an insert into a table that has a BEFORE row Trigger.

    When you hard code the values into the INSERT statement, the trigger works fine.

    For example:

    INSERT
    INTO content (cont_name,cont_seg,cat_seq)
    VALUES('blah',100,200);

    1 row created.

    However, your trigger errors with ERROR ORA-4091 with
    INSERT INTO...select statement:

    INSERT
    INTO content (cont_name,cont_seq,cat_seq) (select....from category);

    ERROR at line 1:
    ORA-4091: table <schema>.CONTENT is mutating, trigger/function may not see it
    ORA-6512: at "<schema>.INS_CONTENT", line 4
    ORA-4088: error during execution of trigger '<schema>.INS_CONTENT'


    TRIGGER:

    CREATE OR REPLACE trigger INS_CONTENT
    BEFORE INSERT on CONTENT
    FOR EACH ROW
    DECLARE
    max_sort number;
    BEGIN
    SELECT max(cont_sort) INTO max_sort FROM CONTENT;
    IF max_sort IS NOT NULL AND max_sort!= 99999 THEN
    IF :new.cont_sort IS NULL THEN
    :new.cont_sort := max_sort +1;
    END IF;
    END IF;
    SELECT SEQ_CONT_SEQ.nextval INTO :new.CONT_SEQ from dual;
    END;


    Explanation
    -----------

    Error: ORA 4091
    Text: table %s.%s is mutating, trigger/function may not see it
    -------------------------------------------------------------------------------
    Cause: A trigger (or a user defined PL/SQL function that is referenced in
    this statement) attempted to look at (or modify) a table that was
    in the middle of being modified by the statement which fired it.

    Action: Rewrite the trigger (or function) so it does not read that table.

    Explanation:
    You cannot look at or modify the table that is mutating.

    Note:
    From the Application Developers Guide
    "There is an exception to this restriction;
    For single row INSERTs, constraining tables are mutating for
    AFTER row triggers, but not for BEFORE row triggers.
    INSERT statements that involve more than 1 row are not considered
    single row inserts."

    "INSERT INTO <table_name> SELECT ..." are not considered single row
    inserts, even if they only result in 1 row being inserted.


    RELATED DOCUMENTS
    -----------------

    Oracle Application Developer's Guide (A68003-01)
    Chapter 'Using Database Triggers', page 13-22)

    posted @ 2007-04-27 22:36 john 閱讀(4336) | 評論 (3)編輯 收藏

    房地產綁架了中國經濟(轉)

    搜狐博客 > 江湖一聲笑 > 日志 > 經濟述評 2007-04-20 | 房地產綁架了中國經濟(王超,轉) 房地產綁架了中國經濟,全國性的泡沫已經形成!!!
    標簽: 投資  呼和浩特  上海  深圳  房價 
          經過幾年的持續上漲,深圳、上海、杭州、北京、廣州等一線城市的房價,已達到“一套房消滅一個百萬富翁”的水平。
      高速膨脹的地產,不但在不公正擠占社會財富,也擠占了其他產業的發展空間。
      價格高的商品房,不但抬高了社會生產、生活成本,削弱了中國在全球的競爭力,也讓中國經濟變得脆弱,出口依賴度直線上升。
      經過三級市場的成功滲透,在一些城市,房產市場形成了“先富起來的人對未富者進行掠奪”的市場格局。
        
      地產綁架了中國經濟
      十五期間,一些地方政府相繼將“地產”列為“支柱產業”的結果,導致這一行業迅速跨越它在產業鏈中本有的位置,成為中國經濟中的一個“異數”。脫離社會實際支付水平的房價和龐大的開發規模,在使“地產行業”不正當占用了過多社會財富的同時,大大削弱了中國居民在其他領域的購買能力,并對其他產業的發展形成強硬擠壓。 “2005年,中國經濟出口依賴度接近70%”這一數據,實際也在傳遞這樣一個信號:在醫療、教育、尤其是價格居高不下的房產的交替作用下,中國本就不均衡的市場購買力在進一步萎縮,以致不得不加重對國外市場的依賴,中國經濟的脆弱性幾乎已到了“生死存亡”的危險關頭。
      可以說,連續5年的“地產高燒”,已給中國經濟、社會的可持續發展注入了多種隱患,近年各主要城市由地產開發支撐起來的、看起來讓人滿意的GDP增長數據,一經細分,完全可以成為這些隱患嚴重性、廣泛性、真實性的證據。而更為嚴峻的是,作為不動產,房地產實際是一種終端行業,牽涉著數十種上游產業,比如從2004年開始,房地產就消耗了國內差不多一半的水泥和鋼材,這意味著,由房地產直接按放在中國經濟中的隱形炸彈,除了目前銀行已知的近4萬億房貸外,還有數十個相關行業為滿足房地產膨脹所帶來的硬性需求、擴大產能所進行的數目龐大的基礎投資。它的崩潰,不僅僅只關涉到我國的金融安全,同時也關涉到我國的產業安全。而2005、2006兩年,國內絕大部分城市房價在國家連續出臺的宏觀調控政策下,繼續強硬上揚的事實,似乎在進一步表明:地產綁架了中國經濟。
        
      尋找“湯臣一品”
      2006年8月以11萬每平方米開盤的上海豪宅“湯臣一品”,在《上海證券報》爆出其地價僅為每平方米4000多元后,被眾多網絡人士一致推為“中國地產泡沫與暴利”的最佳代表。
      但是,另人沒想到的是,這個熱遍網絡、堪稱中國最知名的樓盤,竟是這樣難找。
      據悉,2007年1月7日,在上海外國語學院附近,一記者連續攔了5輛出租車,告知“去湯臣一品”,5位司機均一臉茫然,即使記者一再解釋這個小區“坐落在陸家嘴,距金茂不遠、是中國最昂貴的樓盤”,這些本該對上海地理滾瓜爛熟的司機還是大搖其頭,表示“從沒聽說過,不知在哪里”,無奈之下,記者只好請出租司機先到陸家嘴,邊轉悠邊問。
      進入陸家嘴地盤,出租司機連續三次下車,用本地話向路邊的賣店、飯店打聽“湯臣一品”在哪里?都失望而歸,在漫無目的地搜尋了幾條街后,司機才在一座快要竣工的寫字樓前,從一個負責施工的技術員那里打聽到了湯臣一品的確切位置。原來這座聲名在外的“中國最昂貴的樓盤”,在距金茂大約一站地的花園橋西路和拾步街之間。
      在“湯臣一品”小區的圍墻外,這個年近50歲的司機在瞇著眼仔細看了一番矗立在車窗外的“中國最昂貴的樓盤”后,突然沒有節制地大笑起來,邊笑邊搖頭,嘴里還不住叨咕:“湯臣一品,每平方米11萬”,每叨咕一遍就笑得更厲害,他瞅著湯臣一品裝飾豪華卻空空蕩蕩的售樓中心,最后竟笑趴在了方向盤上。出租司機的突然失態,讓約10米外兩個本來筆直站著的保安變得非常尷尬,訕笑著望著我們。
      過了約3分鐘,出租司機才慢慢恢復常態,他向記者表示歉意,說自己突然莫名其妙想起了《大腕》里那個說起話來滔滔不絕的神經病。
      湯臣一品所在的區域,被稱為小陸家嘴,這個面積僅1.7平方公里的彈丸之地,密布著中國最昂貴的豪宅,半年前,一個當地記者計算出,按照當時該區域的平均房價,僅在1/10的地面建造40層的高樓,其市值就與上海股票交易所的全部股票市值相當。“任何一幢樓都抵得上幾家上市公司的流通市值”。
      一業內人士告訴記者,雖然自己并不看好湯臣一品的銷售前景,但卻無法忽視這個樓盤為上海乃至中國地產帶來的強烈象征意味。
      “每平方米11萬”所傳播的地產價值暗示,在為上海現有高價樓盤的價格敏感度松了綁的同時,可以拉高周邊、上海其他區域乃至全國多少高檔樓宇的售價?同時他認為,湯臣一品在國家連續三年、一年比一年嚴厲的宏觀調控政策下橫空出世,是目前中國地產有些失控的最好注腳。
      雖然,上海號稱最近8個月商品房價格指數在連續下跌,但實際上,上海內環的大多數一手房、二手房依然處于微升狀態,2006年,上海商品房總竣工約3000萬平方米,而同期銷售僅1000萬平米出頭,當年積壓近2000萬平米已成定局。
      由于民間輿論和宏觀調控帶來的雙重壓力,從2005年上半年開始,上海調整了自己對地產的宣傳定位,開發商與消費者隨之進入明顯相峙狀態,但國內其他城市卻迅速接過了上海手里的接力棒。首先是深圳,從2005年9月份開始,當地房價以每月5%左右的速度一路狂漲,有的月份上漲幅度甚至突破10%,到2006年初,深圳關內已經鮮有一萬以下的一手房,二手房價格也飆高到8000元每平方,隨后,北京開始發力,2006年6、7、8、9月,北京房價同比分別上升11.2%、11.1%、11.4%和10.3%,不斷“領跑”的結果是,至冬季房展,北京五環內一萬以下的一手房幾乎絕跡,三環周邊的二手房均價追至8000,12月底,這些地域的二手房也突破萬元大關。
      廣州、南京、福州、武漢、成都、沈陽、哈爾濱、烏魯木齊、西安、大連、青島、寧波、蘇州……國內幾乎所有區域經濟中心城市,都跟在北京、深圳這兩部經濟引擎后面,價格一路追高;這樣的氛圍,甚至讓公認為是中國地產過熱的重災區杭州,在2006年也開始蠢蠢欲動,雖然早在2004年,就有人指責“杭州開發商囤積的土地,足夠杭州開發五至十年”,但2006年初,當地媒體用“全線飄紅”來形容了政府當年舉行的第一次土地拍賣;這表明,導致杭州房價上漲的市場機制并沒有改變,由地方政府、開發商及其附屬利益團體組成的“鐵三角”,依然把控著當地市場的節奏和走向。
      2006年3月,一些與地產界關系密切的上海本土專家,以學者身份四處接受采訪,宣稱上海地產觀望期已經結束;國內包括上海當地不同地段間的區域差異是一種客觀存在,這種差異決定了上海黃金地段的高檔樓盤還有上漲空間;在市場經濟環境下,投機是一種正常的經濟行為,可以拉動產業的快速整合,打壓這種行為有違市場經濟規則;政府不應過多插手上海地產問題,而應交由市場去自行調節。
      6月,呼和浩特市政府悍然反擊新華社關于“政府這只有形的手在拉高當地房價”的新聞報道,將其拔高到影響“民族和諧”這一政治高度,強調呼和浩特的地產開發完全是“按照中央核準的規則在進行”,呼和浩特的房價“是本地經濟和城市化快速發展的結果”。呼和浩特政府從“2004年至今,投資于經濟適用房的投資占整個房產開發投資的54%”,所以“呼和浩特商品房的結構也是健康的”。不過,5個月后,由該市房產局提供的“2006年1-10月呼和浩特房地產市場形勢分析”卻顯示,呼和浩特這一時間段的“經濟適用房施工面積占住宅施工面積的比重為8.72%”。且這一比例不但比去年同期“提高了1.13個百分點”;而且環比“也呈現較明顯的提高”;統計顯示,“發展健康”的呼和浩特地產開發市場,商品房均價已從“2004年的1590元每平方竄至2006年的3481元每平方”,短短兩年升幅高達218.89%。同時,與高達3481元的均價形成鮮明對比的是,2006年1-10月該市的土地購置費每平方米僅為509元,2005年更低至每平米374元。
      2006年1-10月,呼和浩特商品房竣工率僅13.02%,去年同期更低,為11.23%,不到全國平均竣工率的1/3,這意味著:呼和浩特房地產開發商囤積土地的跡象非常明顯。與這一低竣工率對比鮮明的是,呼和浩特住宅銷售速度遠高于同期的竣工率,1-10月, “呼和浩特共竣工商業住宅竣工58.69萬平米,銷售76.98萬平米”,實際銷售率出現了國內其它城市罕見的一個數字:131.16%,其中僅在10月份,呼和浩特商品房預售面積就達13.43萬平米,比去年同期狂增206.6%,有專家認為,聯系它超低的竣工率來看,這一反常比例,除可能有呼和浩特市政府姿態強硬的聲明引起市場追風效應外,也不排除“開發商在人為控制市場供應量”。

      房價上漲之源
      究竟是什么因素導致了最近幾年中國城市房價的持續上漲?
      在眾多關于房地產上漲因素的分析中,幾乎沒有人注意到深圳于2001年3月26日開始正式實施的《深圳市政府100號令》,事實上,由該法令所確立起來的國內地產市場的運作原則和模式,與最近幾年全國范圍房價一路追高有著極深的淵源。
      由于內容主要是由“當地土地主管部門在親自操刀”,加上具體參與者對“市場經濟的復雜性知之甚少”,過于迷信香港經驗,導致《深圳市政府100號令》這一有“國內第一個規范地產市場運作規則”之稱、本意為“防止劃撥、協議轉讓土地過程發生腐敗”的地方法規,在客觀上幫助主管部門完成了對土地和房產開發的統控,并否定了其他市場主體的功能和作用,強行終止了此前存在于商品住宅市場的多樣化特征,將滿足居民住宅需求路徑高度統一在了“以商品房為主體的市場模式上”。
      2001年前,城鎮居民的住宅解決途徑有《城鎮個人建造住宅管理辦法》、《國務院關于進一步深化城鎮住房制度改革、加快住房建設的通知》兩個法規可依,這兩個法規一個在“鼓勵城鎮個人建造住宅”,另一個則明確要求各地“建立和完善以經濟適用住房為主的住房供應體系”,也就是說。各地商品住宅的市場主體應為“經濟適用房”。
      各地依據這兩個法規形成的市場體系,讓當時的城鎮居民至少可以通過以下幾種途徑滿足住房需求:集資建房、合作建房、經濟適用房和純粹的商品房。
      但是,“100號令”通過確立“土地局是土地交易唯一合法的部門”,將土地交易、包括第二次、第三次土地交易大權,收歸一個部門統控,要求深圳所有土地及其地上附屬物的交易,都必須由土地局直屬機構----深圳市土地交易中心以“拍賣為主、掛賣為輔”的方式 “公開、公正、公平”進行,這些規定,在符合了形式上的規范與透明外,也衍生出了“地產市場功能單一、難以承載城市多樣化的用房需求,土地局職能從此前以管理和監督為主變成了坐莊城市地產開發的‘土地爺’、可以輕易調控房產開發的規模與節奏、權力一枝獨大,政府與開發商易形成市場同盟、直接與民爭利”等弊端;同時,由于合作建房、集資建房的操作路徑與這一法規所確立的交易規則無法兼容,導致商品房市場的多元化特征被迫實際終止,加上本應形成制約關系的房產、土地、規劃、甚至勘探部門,在深圳全部歸口在土地局,這無疑進一步強化了土地局對整個市場的集權程度。有學者一針見血地指出,這一法規實質具有這樣的含義:(深圳)政府把老百姓的住房利益整體出售給了開發商。
      基于當地各界對《深圳市政府100號令》意見極大,當時在新華社廣東分社就職的記者曾于2001年9月,三次前往深圳進行專題調研,得到的情況反饋是:為了反擊社會負面評價,鞏固這一政令,深圳土地局不惜耗費巨資、以每月支付10多萬宣傳費為代價,邀請國內外知名媒體前來為它“唱贊歌”,同時還廣邀其他省市的同行前來觀摩“這一經驗”,試圖通過“以最快的速度在國內推廣”的方式,讓其成為既成事實。記者曾在深圳土地交易大廳的貴賓記事本上看到,沈陽、山西、安徽、河南等地的土地管理部門官員,已在那個豪華的記事本上留下了不少溢美之辭,此外“還有不少省市的主管部門官員也將陸續到深圳土地局來考察”。
      記者在隨后形成的內參報告中,曾明確擔憂“這一法規實際終止了此前地產市場其他市場主體的合法地位,導致市場發育嚴重單極化,重新回到壟斷狀態,實質是市場經濟的一個退步,并將給房產市場帶來不可預知的發展隱患”。
      不過,深圳市的“新舉措”,卻讓一些財力匱乏、當地房地產市場又啟動艱難的地方政府如獲至寶。迅速按這一口徑調整了本地房地產市場的結構與運作模式:土地房產局坐莊房產開發市場,有購買需求的城市居民則幾乎全部被驅趕進了商品房市場。
      效果立竿見影。
      以沈陽為例,2001年,沈陽房地產營業額約55億,虧損2億余元,這一年,整個遼寧省的土地轉讓收入僅為1.6億元。但從2002年實行“土地集中拍賣”政策后,沈陽地方財政來自房地產收入直線上升,當年,沈陽地方財政近1/3來自土地出讓金和房地產稅收。牛刀小試嘗到甜頭后,沈陽——這個中國最重要的重型機械制造基地,索性將房地產列為了該市的支柱產業,2003年,它把超過1/3的固定資產投資投向了地產,同時,約1/3的地方財政收入也來自房地產開發,2005年,在遭遇宏觀調控之后,沈陽地產投資依然保持了超過20%的增長速度,僅收取的土地出讓金和配套費用就高達42億。
      由于這一模式下的房地產開發能快速拉高當地GDP、并迅速改善地方政府的財政狀況,相當部分地方政府以前所未有的熱忱投入到了房地產大開發中,“以經濟建設為中心”被實際壓縮成了“以房產開發為中心”。同時,這一標榜“公開、公平、公正”的市場模式,并沒有遏制住房地產領域的腐敗,反而讓腐敗愈演愈烈,據知名旅美學者徐滇慶介紹,經不完全統計,最近幾年,中國主要城市流通在房地產市場的資金,有高達1000多億不知去向。
      在市場經濟里“后知后覺”的呼和浩特,由于開始階段沒有跟風,直到2004年當地商品房均價才1590元/米,看到其他兄弟城市干得風生水起,呼和浩特失落之余,終于琢磨出了這其中簡單的道理,于是2004年該市也如法炮制,將“土地收儲中心”調整為政府直屬機構,開始通過統一的“掛拍賣”坐莊房產開發市場,果然,遠在內蒙古大草原的呼和浩特,房產市場也頓時風生水起,2005年,該市商品房均價達到2500元左右,2006年,均價接近3500元。在呼和浩特此輪漲價旋風中,政府每年拿到了幾億的小頭,開發商拿到了十幾億的大頭,當地老百姓則得為“這一規范的市場運作機制”多掏十幾億房款。

       一組可怕的數據
      在一個國家的產業鏈條中,房地產究竟應該處在一個什么樣的位置?
      上海交通大學經濟管理學院孟憲忠教授表示:在一個經濟體系的產業鏈中,房地產既是一種基礎性產業,也是一個對其它產業的發展具有嚴重依賴性的產業。后一個角度,表示房地產市場與其他經濟活動所創造的財富值之間,存在一個對等的比值關系。通俗地說,就是一個社會創造財富的多少,決定它房地產市場的繁榮程度和房價高低。
      綜合世界各國的情況看,一個健康的房地產市場,其在社會總投資中所占的份額應在10%左右,超過這個份額就會出現投資過熱,它帶來的負面影響是降低社會資源配置的合理程度,引起社會不必要的財富損耗,甚至成為社會財富的殺手,并損害產業間的平衡協調。從經濟健康和可持續的角度,商品房價格與當地家庭年均收入之間,也有一個比值,這個比值根據不同國情,在1:3至1:6之間,超過這一比值,房地產就不但在不正當剝奪購買者的財富,也會從整體上削弱社會對其他產品的購買能力,給其他產業的發展帶來障礙。
      按照這一判斷標準,最近幾年,國內主要城市的經濟發展數據,傳達出的是一個社會資源長期配置錯位、明顯存在嚴重經濟隱患的信息——
      浙江經濟圈的中心城市杭州,2003年社會固定資產投資1006.18億元,其中房地產開發328.54億元,占全部固定資產投資的32.6%,全市財政總收入達329.71億元,土地出讓所得109.29億元;2004年社會固定資產投資1205.18億元,其中房地產開發企業完成投資328.54億元,占當年社會固定資產投資的27.26%。2005年,該市房地產開發投資更上層樓,達到410.57億元。
      珠三角重鎮廣州,2003年完成全社會固定資產投資1157.77億元,其中房地產開發投資405.94億元,占35.1%。2004年完成全社會固定資產投資1321.96億元,其中房地產開發投資440.81億元,占33.3%,2005年完成社會固定資產投資1445.33億元,其中房地產開發投資488.86億元,占33.7%。
      華東六省一市的經濟龍頭上海,2003年完成固定資產投資2452.11億元,其中房地產開發投資901.24億元,比重為36.8%。2004年完成全社會固定資產投資3084.66億元,其中房地產開發投資1175.46億元。比重為38.1%,2005年完成全社會固定資產投資總額3542.55億元,其中房地產開發投資1246.86億元,比重為35.2%。
      中國改革的窗口深圳,2003年完成全社會固定資產投資額946.49億元,其中房地產開發投資410.06億元,占43.4%;2004年全社會固定資產投資額1090.14億元,其中房地產開發投資432.01億元,占39.6%,全年完成地方財政一般預算收入321.75億元,國土基金總收入128.46億元,2005年完成全社會固定資產投資1176.13億元,其中房地產開發投資418.76億元,占33.%。
      中國政治中心、中國北方重要的經濟中心城市北京,2003年完成全社會固定資產投資2157.1億元,其中房地產開發投資1202.5億元,比重55.7%,且僅比上一年多了1.2個百分點。2004年,北京全社會固定資產投資2528.3億元,其中房地產開發投資1473.3億元,比重為58.2%,2005年完成全社會固定資產投資2827.2億元,其中房地產開發投資1525億元,比重為53.9%。
      中國北方重工制造中心沈陽,2003年完成全社會固定資產投資582.6億元,其中房地產開發投資177.3億元,比重為30.1%;2004年全社會固定資產投資971.4億元,其中房地產開發完成投資342.6億元,比重為35.2%,2005年固定資產投資完成1363.2億元,其中房地產完成投資413.6億元,比重為30.3%。
      中國經濟大省省會南京,2003年完成全社會固定資產投資額954.04億元,其中房地產開發投資183.80億元,比重為19%;2004年完成全社會固定資產投資額1201.88億元,其中房地產開發投資292.88億元,比重為24.3%,2005年完成全社會固定資產投資額1402.72億元,其中房地產開發完成投資額296.14億元,比重為21.1%。
      華中樞紐武漢,2003年全社會固定資產投資完成645.06億元,其中房地產投資169.55億元,比重為26.2%,2004年全社會固定資產投資完成822.20億元,其中房地產投資233.30億元,比重為28.3%,2005年全市完成全社會固定資產投資1055.18億元,其中房地產開發投資297.99億元,比重為28.2%。
      這些城市,都是中國最重要的經濟發動機或區域經濟中心,但最近5年來,這些發動機都把自己的經濟引擎按放在了“不動產”上,將超過30%的全社會固定資產投資投向了房地產,有的這一比例更高達50%,遠遠高于10%的正常水平。由于房地產的強力拉動,它所必然引起的投資過熱也相應凸現,雖然從2002年開始,國家宏觀經濟部門就開始不斷警告我國經濟出現了投資過熱,但依然無法阻擋這股氣勢兇猛的洪流,2003年,我國全社會固定資產投資增26.7% ,2004年第一季度,全社會投資突然增速,同比增長高達43%,不但比上年同期加快了15.2個百分點,也遠高于1992和1993年我國經濟過熱時全社會固定資產投資所創下的29.1%和35.2%這一增速;2004年全年,我國全社會固定資產投資達70073億元,增25.8%;2005年我國全社會固定資產投資88604億元,增25.7%;2006年上半年,全國固定資產投資較去年同期增31.3%。此外,我國在建項目規模2005年為27萬億元,2006年底則飆高至32萬億元。
      一從事宏觀經濟研究的專家告訴記者:很難想象各地政府為什么會進行這樣的投資分配,因為這給整個經濟結構帶來的破壞和隱患極其明顯,房地產膨脹所帶來的“真實而強勁”的市場需求,必然帶動與其相關的數十個產業的膨脹,所以房地產熱一定會引發整個社會投資的過熱。
      他表示,地方政府通過整合強大的政策和市場資源,可以在短時間內維持房地產市場份額在整個社會產值中占到一個較高比例,但這樣的高比例絕不可能長期持續,這是由房地產在產業鏈中本有的位置所決定的,于是問題出現了-------由房地產拉高的上游相關產業的產能很快就將被懸空,如果這個懸空的程度大到了產業自身無力消解,就會發生我們擔心的經濟蕭條甚至產業崩潰。
      宏觀調控發生后,一些學者從房地產拉動了多少份額的產品消費,以此證明房地產對GDP的重要貢獻,完全可以從另一個層面求得房地產膨脹導致的產業隱患規模。
      “最近幾年,各地政府對GDP的理解存在一個誤區,就是只重數字增長卻不分析經濟行為的合理性,事實上,GDP的參考價值與被分析對象行為的理性程度是成正比的,經濟行為愈理性,GDP的參考價值愈高,反之則愈低,所以,針對目前各地贊歌不斷的GDP,可能我們最該去關注的是,這些GDP背后的經濟行為的理性程度究竟有多高?現在中央倡導的科學發展觀,不僅僅要求各地不得以‘經濟發展’替代‘社會發展’,而且也內含著提高決策、資源配置、經濟行為理性的訴求”。

      一場危險的游戲
      除投資規模過于龐大外,房地產另一個問題更為突出——主要城市的商品房價格已遠高于社會實際購買能力。
      即使最堅定支持“房地產價格應由市場去調節”的人也會同意,房價與所在地居民收入之間,應該存在一個合理的系數,這個系數,聯合國人居中心的上限是3:1,世界銀行的上限是5:1,意思是“一個擁有當地平均收入水平的家庭,用3-5年的收入總和,可以購買到所在地平均價格、平均居住面積的住房”。
      按照這個標準,中國幾乎所有主要城市的房價,已連續數年嚴重超過這一標準。其中,“中國著名的經濟中心長三角的各大城市,平均房價收入比超過理性房價收入比的1.93倍,杭州、上海、南京、寧波的比例更超過2倍甚至達到3倍的比例”。國務院發展研究中心一位部門負責人對記者坦陳:按照目前的房價,他是買不起房子了。
      2001年,中國房地產被外界形容為“出現局部過熱”時,全國房價只有深圳、杭州、溫州商品房均價超過了5000元/米,廣州、北京接近5000元/米,上海商品住宅均價3413元/米,內環邊5年左右房齡的二手房價格保持在2500元左右,全國35個納入物價指數統計的大中城市中,廈門、杭州、南京、沈陽、大連、天津、哈爾濱、昆明、福州、海口等地商品房價格在2000-3000元/平方米之間;其他21個城市商品房價格在2000元/平方米以下。到2006年底,這些城市的商品房均價幾乎都翻了一倍。深圳、上海、杭州、北京、廣州的房價,已達到“一套房消滅一個百萬富翁”的水平。
      2006年底,由中國金融網發起的“中國城市房價究竟高了多少”的網絡調查,截至2007年1月6日,有11%的網友認為高了30%,24% 認為高了30-50%,65%認為高了50%以上。
      有學者認為,這一調查數據顯示出的結果與現實情況比較吻合,他說,即使按照世界銀行公布的家庭收入與房價5:1這個上限來看,經過最近幾年的漲價風潮,我國絕大部分一、二線城市的房價已遠遠超標,比如上海,2005年其人均可支配收入為18645元,其家庭人均人口3.1人,年總收入為57799.5元,5年總收入為288997.5萬,這個數據體現的是當地實際發展水平和實際購買力,當年上海人均建筑面積達33.07平方米,按照這個實際購買力和當地人均居住面積之間形成的系數,它的住房均價應該為4171元/米,與它2002年上半年平均房價相當,但實際上,這個數據同期變為了8627元;深圳2005年人均可支配收入21494元,按照當時全國城鎮人均住房系數,它的住房均價應該為4578元/米,但深圳2001年的商品房均價就高出這個數字近千元,同期實際均價為6952元 ;北京2005年人均可支配收入17653元,理性房價上限為3760元,但實際為6232元;廣州2005年人均可支配收入18287元;理性均價上限為3895元,但實際為5660元;南京2005年人均可支配收入14997元,理性均價上限為3194元,但實際為4960元;杭州2005年人均可支配收入16601元,理性均價上限為3536元,但實際為7029元; 青島2005年人均可支配收入12920元,理性均價上限為2751元,但實際為4639元;成都2005年人均可支配收入11359元,理性均價上限為2419元,但五城區實際為4085元;武漢2005年人均可支配收入10850元,理性均價上限為2311元,但實際為3300元;沈陽2005年人均可支配收入10098元,理性均價上限為2151元,但實際為3330元;呼和浩特2005年人均可支配收入12150元,理性均價上限為2588元,但實際為3481元。
      他說,這其實意味著,我國大部分城市在進行一場危險的游戲,這場游戲以高昂的房地產為核心,在全面拉高中國固定資產投資的同時,通過抬升城市辦公、居住、生活成本,大幅增加企業的運轉經費,以行業暴利的方式追漲企業成本。導致我們不惜以犧牲環境、一線工人合理工資收益和合理稅收等途徑積攢起來的成本方面的競爭優勢,正在被這一行業暴利全部甚至超額吞噬。從而瓦解我們在全球范圍的競爭優勢。
      這一態勢已得到一些國際機構的調查印證,2006年9月26日,總部設在瑞士日內瓦的世界經濟論壇公布的《2006~2007年全球競爭力報告》就顯示出,2006年,中國的競爭力繼續下跌,相比2005年再后延了6個位次,已落后印度11個位次。
      在這樣嚴峻形勢下,如果依然以“穩定房價”為指導思想來進行宏觀調控,這場游戲完全可能“以房產暴利開始,以產業崩潰結束”。因為目前的房價已不應該得到“該去穩定”的結論支持,這個觀點不是從一種市場博弈角度給出的,而是依照目前社會實際購買力進行比較衡量的結果。
      房地產不但在吞噬城市競爭力,也在吞噬購房者的生活。
      2006年初,來自《半島晨報》的調查表明,由于超高的房價,在大連,有4成購房者感到生活質量明顯下降,有3%的購房者感到生活質量嚴重下降,而幾乎就在這同一時間段,一篇名為《高房價導致中國90%白領消失》的網絡文章,在不少論壇成為一個被競相關注的熱點,雖然該文所羅列的數據不一定全部真實,但它提出的“(相當部分)購房白領被房產套牢”的觀點,被隨后《中國青年報》公開的一份統計資料證實,該資料顯示,我國貸款買房的群體中,有54.1%月供占其收入的20%~50%,31.8%月供占到了其收入的50%以上。而在國際上,月收入的1/3是房貸按揭的一條被公認的警戒線。美國銀行就明確規定,每月償還的按揭貸款以及與住房相關的稅費,不得超過貸款人稅前收入的28%。
      針對這一問題,知名房產問題專家章林曉曾撰文警告:根據聯合國《國民經濟核算統計年鑒》和各國統計年鑒,以美、英、法、日為對象,分析它們GDP達1000美元時居民消費結構可以發現,其住房消費支出比例最大的英國為13.8%,最小的法國為8.3%,均低于我國同期水平數倍。他據此認為,這意味著,房地產業在不正當剝奪整個社會的財富。而“這破壞了社會的財富配置,既進一步擴大了社會的貧富分化,給社會帶來了不安定,也不利于其他產業的發展,因為社會總體購買力被這個必需品過多地擠占了”。

      誰在分攤高房價
      在國內一些一線熱點城市,經過一、二、三級市場整合后,當地高昂的房價正在從主要由購房者分攤,逐漸變成由全社會在分攤。
      這一分攤的路徑主要有兩種,一是通過提高三級市場的房租,將高昂的房價直接轉給租房者,二是轉化為各類企業、尤其是服務性企業的經營成本,再由這些企業通過提高服務或銷售價格轉嫁給社會。
      有專家認為,這種轉嫁因素,或者說商品房的租售比,實際是深圳、北京兩個熱點城市2005年底以來房價持續上漲最重要的支撐點。
      在深圳關內,一個3-5年房齡、面積100平米的小區商品房,可以輕松租到3500-4000元/月,按一年出租10個月計,年收益在3.5至4萬元之間,即使按一萬元/米購入,這一投資的年收益也在3.5%-4%之間,如果再加上保值預期,它的投資收益要大大高于同期發放的長期國債。
      而據記者所知,中國政府2006年所發放的1950億元長期國債,在全國范圍都受到了瘋狂追捧——
      上海,市民為買國債很早就在網點前排起了長隊,中行位于徐家匯和陸家嘴地的支行,營業頭一個小時就售出國債近400萬元,農行在對單筆大額做出限制后,竟然在短短半小時就把國債全部售光;重慶,短短幾個小時,一億多國債就被搶購一空;昆明,商業銀行門口購買國債的市民排起了長隊。幾小時內其所承銷的2.4億國債就全部脫手;南京,市民“手拿油條搶購國債”,商業銀行“只花了10多分鐘,就賣完了所承銷的全部1.5億元國債”,興業銀行也在十多分鐘內,在全國賣完了1.5億的國債配額;合肥,各銀行承銷網點都出現了排隊搶購場面。首發當日上午10時許,大部分銀行承銷的國債就已售空。甚至蕪湖、大慶、蘇州這些二三線城市,國債也都出現了空前的熱銷。
      “這些國債,3年期票面年利率3.14%,5年期國債票面年利率3.49%,均低于投資深圳二手房的所得收益”,該專家問記者:“如果你手頭有足夠的錢,又找不到其他投資途徑,給你長期國債和投資深圳的房子賺取租金收益兩個投資途徑,你會怎么選擇”?
      北京、上海的情況與深圳類似,在北京,三環附近一間普通的、面積在65米左右的兩房一廳小區房,2005年年中的月租金在2300元左右,2006年漲到了2500元,10個月租金收益在2.3萬-2.5萬。按1萬/米計算,年收益在3.5%至3.8%之間。也高于熱銷全國的長期國債。
      上海,內環邊45平米左右的一房一廳,租金價格一般在1500-1700之間,10個月資金收益1.5萬-1.7萬,按目前8000元/平方米的價位,回報在4.17%-4.71%之間。二房的租金收益,也大體與此相當。
      于是,從房地產本身這個角度來判斷,上海2003-2005年、北京深圳2005-2006年房價漲幅之快,價格之高,雖令人乍舌,但與國內其他一些房價明顯缺乏投資支撐的城市比,卻居然有了最充足也最合理的理由,畢竟二手房已把這一收益變實,而既然3-5年、5-10年的二手房都有這樣的價格支撐,那么一手房均價過萬是再正常不過。這同時意味著,在深圳、北京、上海這樣的城市,高房價已被成功轉嫁給了租房者,實際也就是轉嫁給了社會來分擔。
      在高價位出手的購房者的投資心態,也從實際的購買群體得到了印證,據《深圳特區報》報道,2006年,深圳的購房者有“50%不是自住,全額付款的購房者比例也超過了一半”,投資目的相當明顯。
      這一狀況引起了不少學者的憂慮,有的甚至提出了這樣一個激進的觀點:高房價通過三級市場的成功滲透,讓這場地產高燒變成了“先富起來的人對未富起來的人的一種掠奪”。他說,市場運作必須考慮公平原則,只有這樣經濟才健康并可持續,即使是新自由主義經濟學大師哈耶克,晚年也在花很多時間研究“自由市場道德原則的缺失問題”,并承認這是新自由主義經濟學的一塊硬傷,自己一直沒能令人信服地從理論上找到解決依據。現在這個通過“市場自由調整”而出現的“由全社會來分攤高房價”的局面,從技術層面無可指責,但從它必然引起的不良后果這一角度權衡,這一局面必須扭轉,如果不扭轉,把房價拉回到正常水平無疑癡人說夢,因為很簡單,這是一個導致深圳、北京等一線城市高房價平穩著陸的一塊實地,而這個實地的支撐點則是這些城市相較國內其他城市的更高的競爭力,這個高租金則在“毫無創造地消耗這個競爭力”,并支撐這些城市房價繼續上揚。
      而另一方面,“全國現在有近8萬億存款掌握在20%的人手上,只要這一模式持續,并被愈來愈多的高收入者接受和認同,就會有愈來愈多的人參與進這一模式,一些學者提出的‘讓有錢人買了房子租給無錢買房的人居住’,在這一模式下就變成了不折不扣的‘先富起來的人對后富起來的人的掠奪’”。
      在談到城市房價與可持續發展的關系時,有人打了一個“沙漠中馱金子”的比喻:兩個人穿行沙漠時發現了金子,一個貪心拿了自己拿不動的分量,最后渴死在了沙漠上,一個很理智地拿了一點點,最后終于走出沙漠并致了富。
      “房產開發獲利”,可以看作是“金子”,這個“金子”對于處于發展進程中的城市(穿越沙漠的人)而言,是真實的,但對這個“真實的金子”,城市管理者的理智態度應該是“按照自己能輕松承載的能力”(即按城市可支配收入形成的購買力)去拿,這樣才能順路地一路走下去,否則“會被這個真實的寶物最終壓塌”。
      四川聯合大學南亞研究所歐東明副教授表示,如果建立了理性的產業發展判斷,即使“房產開發既得利益集團”也應該去支持健康的房價,因為這才是行業可持續的根本,最近幾年一些城市客觀上存在的對宏觀調控的抵觸,一定程度在于這些城市的管理者和房產開發既得利益者對產業的平衡與可持續之間的關系認識不足,假如他們通過量性分析得知再這樣走下去,不出幾年等著他們的就將是整個經濟體系的絕對蕭條甚至崩潰,也許他們會重新考慮自己的整個決策。
      他說,在這場地產高燒中,最被誤導的其實還是那些擁有自己住房的普通居民,因為從資產來看,他們是絕對地增值了,這無法不高興。但另一方面,對大多數家庭而言,房子除了滿足居住外別無他用,房產增值除了給了他們一個數字財富外,同時還需要他們去分攤必然高漲的生活支出和服務費用,此外他們還要承擔未來可能的產業崩潰或經濟蕭條。也就是說,這個對他們沒多大實際價值的數字財富,實際大大增加了他們的生活成本和未來風險。

      國內經濟已嚴重受損
      持續數年的高房價給中國經濟帶來的嚴重隱患,正一一浮出水面。
      除直接增加了購房者的支付成本,拉高了中國全社會固定資產投資、使中國經濟始終處于投資過熱狀態外,過多社會財富流向這一生活必需品,以及由此引發的消費預期,使中國本就不均衡的內需進一步不足。最近幾年,中國每年的外貿依存度都以10%左右的速度持續上升,2005年達到80%左右,這引起了不少學者的憂慮——中國經濟在結構上已非常脆弱,而另一方面,世界各市場的貿易保護主義色彩卻越來越濃,這將使中國經濟遭遇不測的可能性大增。
      外貿依存度體現的是一個國家進出口貿易總額在本國國內生產總值(GDP)中所占的比重,它反映的是一個國家經濟對外貿的依賴程度和參與國際分工的程度。從1980年到2001年,美國、日本、德國這些發達市場經濟國家,外貿依存度大體穩定在14%~20%的范圍內。
      但同一時期,在產業結構失衡、第一次分配嚴重不公、社會保障不足、經濟策略上過度依重國外市場等原因的交替作用下,中國的外貿依存度一路升高,2001年后,由于住房因素進一步拉低了社會消費能力,中國的外貿依存度更陡然提速,每年以10%左右的速度躥升。當年突破50%大關,2003年達到60.2%,2004年超過70%。2005年,中國全年進出口總額超過1.4萬億美元,達到1978年的68倍左右,2006年1~10月份,中國外貿進出口總值達14249.5億美元,同比增長24.1%,已超過2005年全年水平。
      有學者表示,從好的方面看,外貿依存度體現了中國經濟的開放程度,表明中國參與全球一體化進程加速,中國經濟與世界經濟已經形成了相互依賴的伙伴關系;從不好的方面看,這其實是國內市場需求不旺的一種必然選擇,也就是說,中國每年的高增長,很大程度上是建立在對外依賴的基礎上的,這一模式在相當長的時期掩蓋了中國經濟存在的問題。
      比如,即使在社會圍繞房地產爭論最激烈的時候,我們也沒有達成這樣一個共識:房地產“抽血”式的聚集社會財富,將強力擠壓其他產業的市場空間,其結果是中國經濟整體走上了一條不歸路。這里面的道理很簡單-----假定社會總財富值是100,正常情況下我們拿20%支付住房費用,30%用于儲蓄,50%用于其他消費,但現在住房占用了過多的財富,綜合值達到了40%甚至45%,由于這是一種必須的消費,所以它必然擠壓消費者用于其他領域的消費數額,于是其他行業分到的社會財富值就會大大縮水。購房的人由于財富值已經入套,他得修改自己的消費計劃和比例,沒購房的人呢?如果他需要買房,也不得不按現行的房價標準修改自己的消費計劃。而購房一族,又是一個社會消費力最旺盛的群體,損害了這個群體的購買力無疑意味著內需市場必然遭遇大幅度縮水。
      由于房價過于畸形,國內市場的縮水規模可以說達到了駭人聽聞的程度,以上海為例,按照世界銀行認同的房價比上限5:1和上海這一時期由可支配收入形成的購買力計算,上海商品房均價應該在4000元出頭,但它的實際均價卻是8000多元,二者相差4000元以上,按4000元計,2004-2005年,上海大約銷售了4000萬平米的商品房,這是什么意思呢?等于說兩年中,僅上海房產市場就不正當地從購樓者那里多拿走了約1600億元。
      “一個上海就擠占了這么龐大的數額,全國加起來是個什么數字?所以我不得不用‘駭人聽聞’這四個字來形容房地產對整個社會的掠奪,而這也必然導致國內其他市場出現嚴重的需求不足,影響經濟的良性與正常”。
      來自于央行的最新統計數據,證明該學者所言非虛,2006年11月23日上午,中國人民銀行副行長蘇寧在接受一媒體采訪時透露,我國最終消費占GDP的比重,已從上世紀80年代超過62%下降到2005年的52.1%,居民消費率也從1991年的48.8%下降到2005年的38.2%,二者“均達歷史最低水平”,居民儲蓄率卻上升了9%。
      而同一時期,世界平均消費率達78%—79%。是我國的2倍以上的水平。
      有“華東六省一市經濟發展火車頭”之謂的上海,可能已率先感受到了由過分偏重房地產帶來的寒意,2005年底,當地社科院在一份年終報告里坦露:2005年1~9月,上海(經濟)出現了比較明顯的收縮,主要經濟指標增速不僅低于2004年同期,而且低于全國同期平均水平,出現了(上海罕見)的“雙低”現象。與此同時,上海的工業增長速度也開始大幅度回落,效益下滑,2005年1~9月份,上海工業增長速度為12.4%,低了全國同期增速3.9個百分點。
      此外,顯示上海經濟發達程度和結構合理性的第三產業比重,最近幾年更是持續下降,上海第三產業的比重,2002年達到歷史最高,為51%,伴隨著房價上升。這一比例開始下滑,2003年為 48.4%,2004年為 47.3% ,2005更低至45.6%。
      這一情況,近幾年在另一個高房價城市-------深圳也類似存在。

      三板斧砍掉地產暴利
      基于上漲過快的房貸和開始在全國蔓延的炒房之風,2003年10月,央行正式祭出“121號文”,針對房地產發出了收緊銀根的信號,開始了本輪宏觀調控。
      但決策者很快發現,與1993年那次“一控就靈”不同的是,這一次,這個帶有預警性的手段,一出手卻如入泥潭,不但悄無聲息,甚至還引起了強硬反彈:房地產開發資金規模在全社會投資總額中繼續高比例領跑,部分地方政府開始在一些公開場合揚言本地房地產發展健康,不存在泡沫。
      宏觀調控得到的結果是:2004-2005年全國范圍房價持續大漲,在這場調控與反擊的較量過程,大連、青島、上海、深圳等熱點城市交替領跑,中國宏觀經濟危機被進一步加劇。
      2006年,中央悍然加大調控力度,從金融、信貸、土地、稅收等方面頻出重手,其中包括“加息”、“征稅”、“國六條”、“規定開發周期,打擊土地囤積”、“90平方米70%”、“限外”、“問責”等,一系列政策步步為營,從“宏觀”延伸到了“微觀”,從“市場”延伸到了“政府管理”。態度不可謂不堅決,措施不可謂不嚴厲。
      但是,全國范圍房價繼續堅挺,2006年10月的統計資顯示,雖然全國70城市房價漲幅放緩,但總體依然處于漲勢,當月房價同比上漲5.5%,環比上漲0.4%,此前一個月,這些城市房價同比上漲5.3%,環比漲幅則與10月持平,其中漲幅較大的北京,三季度房價比上一個季度漲了上千元。對這一形勢,發改委官員給出的說法是,“未來的調控任務依然相當艱巨”。
      為什么1993年一招“收緊銀根”就可以遏制當時瘋狂膨脹的房地產,而本輪調控使用了多得讓人眼花繚亂的手段,卻依然收效不大?
      有專家認為,造成這種反差的主要原因在于,兩者有了截然不同的市場機制和金融環境。
      1993年,地產市場是一個以開發商為主體的市場,地方政府與開發商是一種博弈的關系,加上當時金融體系內外的流動性資本規模不大;中國經濟剛剛走出調整期,城市住宅市場需求平穩;所以對房產開發“一控就靈”。但本輪調控,房地產市場,乃至金融體系的流動性資本數額與回報預期,都發生了劇烈變化。
        首先,地方政府與開發商之間已超越了一種單純的博弈關系,實際形成了利益高度一致的同盟,這一同盟對市場擁有絕對的控制權。導致調控環境變得復雜和微妙,如果調控過程地方政府嚴守一個市場底線,就會大大削弱調控效果。對此,前國家統計局副局長賀鏗甚至直言,不打掉(這種)官商勾結,無法平抑房價。
      其次是經過10余年發展,我國的金融環境也已發生巨變,從“資金短缺”變成了“流動性過剩”,據央行相關負責人透露,目前國內有高達2.6萬億的資金處于流動狀態,在資本貫有的追漲心態下,它們對房地產的支撐作用不容忽視,建行董事長、外管局前任局長郭樹清就曾公開表示,(目前)全國各大城市房價連續數月保持5%—7%的快速增幅,原因之一在于金融體系過剩的流動性。
      本次宏觀調控的失利還在于,調控的調子不到位,甚至部分調控手段是按照開發商持續數年的宣傳、將當前城市商品住宅暗示為了“稀缺性公共資源”,這在一定程度上對房產市場“恰好起到了效果相反的刺激作用”。
      直到2006年三季度,發改委在談到調控目標時,依然將其定位于“穩定房價,抑制上漲”。“這樣的定位不但偏離了目前房產市場的真實狀況,也給了被調控者不恰當的暗示”,緊箍咒不緊,無疑會“影響調控的執行與效果”。
      此外,提高首付,限制外購、征收二手房交易所得稅這幾項調控措施,雖可以在一定程度上抑制炒家,提高商品房市場的真需求比例,但這幾個措施也同時釋放出了這樣的意思——商品房是一種稀缺公共資源。結果反而導致更多流動性過剩資本進場,比如在深圳,2006年有過半的交易均非自住,這部分人“全款購買比例很高,投資目的非常明確”。類似的情況也出現在另一個房價突出的城市——上海,2004年,上海商品房銷售額2064.74億元,新增房貸約800億元,房貸額不足40%,已經顯示出購房者高比例付款趨勢,2005年付款比例更大比例攀升,這一年,上海商品房銷售額1906.05億元,但僅新增房貸約200億元。這意味著,同樣有“相當部分購買者在購買時是全額或高額付款,這是實力買家進場給出的一個強信號”。
      介于這樣嚴重的局勢,未來的調控將走向何方?有專家建議——
      在嚴格執行已頒布的措施,尤其是細化落實“回收閑置土地”以打擊土地囤積,落實“經濟廉租房”制度、以給市場確立趨于正常的價格標準這兩個條款外,還應該針對一些市場苗頭,啟動其他幾項措施,三板斧砍掉房產暴利。
      第一板斧,在北京、廣州、深圳、上海等熱點城市,啟動稅收杠桿,打掉這些城市已出現的由“三級市場將高房價坐實”的現實,并遏制這一趨勢向其他城市蔓延。
      如果不打掉三級市場這一現狀,這些城市的房價永遠掉不下來,而這幾個在中國具有標向意義的城市房價掉不下來,其他城市也就有了高標準的攀比對象,要降房價困難重重。房地產現在的局面就會出現僵持,可能真只有經濟全盤崩潰那一天才能抑制房價。
      由于這一措施是對市場進行細部操作,所以啟動時需制定完善細則,同時須將不同的情況區分開來,比如對同一家庭擁有房屋套數的不同,征收額度不同的稅收:第一套出租房按所得的20%征收,第二套按所得的30%征收,第三套按所得40%征收,第四套按所得50%征收……超過500平米按60%標準征收,超過1000平米按80%征收。
      這一稅收征收的依據是“房地產已嚴重干擾中國正常市場秩序,國家不鼓勵私人過多占有這一公共資源”。如果出租房擁有者拒絕出租,那么應對其收取同樣數額的資源閑置費,如果房主稱租不出去,可將該房納入政府專門機構,由政府按“本市實際購買力所確立的租房標準”統一對外出租,對于隱瞞擁有私房數量的情況,則可以通過“有獎舉報,從重處罰”這一殺手锏予以有力還擊,無限度增加這些房主的博弈風險,同時向社會開放這一領域的監督權力,以強力保證這一措施順利推行。
      第二板斧砍向“假按揭”,一些城市在房價高漲后,出現了 “將房子賣給自己也能賺錢”的畸形市場格局,導致假按揭再次抬頭。而假按揭不但可以大大增加房產開發公司與市場抗衡的實力,形成巨大金融黑洞,實際也構成了金融詐騙,所以必須從嚴、從重進行處罰。
      第三板斧砍向“目前房地產市場由權錢結合所形成的市場聯盟”。
      在某種程度上,這個聯盟是近5年房地產持續上漲的罪魁,而且由它所衍生的市場運作機制單一,不利于形成多極化的市場供應。所以,要恢復房產市場的健康,應同時重視其他市場主體的權利。給予其他市場主體以合法地位,比如近期在國內各城市的合作建房聯盟,政府就應給予明確支持引導,打破由2001年《深圳100號令》后,各地政府所實際形成的壟斷型市場模式。
      事實證明,個人合作建房能有效撕開此前由地方政府和開發商組成的壟斷聯盟,形成新的、趨于合理的市場供給,比如2006年下半年,溫州個人建房合作聯盟在土地交易市場爭得一塊被當地開發商認為價格過高、賺頭不大的“雞肋”地塊后,獲得了5300多元/平米的成品商品房造價,而其周邊的房價為8000多元/平米。深圳,在商品房均價超過8000元/平米的情況下,由當地個人建房聯盟參與的投標,競得了一幢均價只有1600多元/米的二手房,2007年1月5日,記者在與競投負責人林先生通電話時,他告訴記者,“他們所有參與競投的人都哭了”,同時他還透露,春節后,他們合作建房組織將以某種方式正式參與政府組織的土地拍賣。
      政府應該大力支持個人合作建房的理由還在于,發生在溫州和深圳的事實表明,這一形式打掉的只是開發商的暴利,由政府主控的一級市場所損并不大。此外,由于目前個人合作建房與市場比較存在明顯的成本差異,一些不法商人也可能會打著合作建房的幌子套錢,政府的積極參與,有利于這一目前尚處于雛形的市場形態的良性發育。
      該學者還特別強調了調控措施中建設“廉價出租房”的重要性。他建議,未來中國城市的住宅供應,應吸取新加坡模式,以“經濟適用房和廉租屋”為手段,加大政府在這一市場領域的作為,使城市房產供應重返1998年由《國務院關于進一步深化城鎮住房制度改革、加快住房建設的通知》所確立的“以經濟適用房為主體、以商品房為補充”的市場格局。
      他認為,這不但可以為房產市場提供一個具有良性導向的新標準,而且可以轉移因房地產市場變化而損失的財政收益,以上海為例,如果每年由政府按當地實際購買力提供1000萬平米的廉價房,地方政府在房產領域的財政收益其實根本不會減少。
      “更重要的是,這一措施也可以使中國的城市化進程得以實際啟動,困擾中國多年的產業轉型和社會轉型問題,將隨之被打開一個順暢的通道”。


     

    posted @ 2007-04-21 10:17 john 閱讀(619) | 評論 (0)編輯 收藏

    Oracle ---管理UNDO表空間

    10.管理UNDO表空間.

    UNDO表空間用于存放UNDO數據,當執行DML操作(INSERT,UPDATEDELETE),oracle會將這些操作的舊數據寫入到UNDO,oracle9i之前,管理UNDO數據時使用(Rollback Segment)完成的.oracle9i開始,管理UNDO數據不僅可以使用回滾段,還可以使用UNDO表空間.因為規劃和管理回滾段比較復雜,所有oracle database 10g已經完全丟棄用回滾段.并且使用UNDO表空間來管理UNDO數據.

    UNDO數據也稱為回滾(ROLLBACK)數據,它用于確保數據的一致性.當執行DML操作時,事務操作前的數據被稱為UNDO記錄.UNDO段用于保存事務所修改數據的舊值,其中存儲著被修改數據塊的位置以及修改前數據,

    UNDO數據的作用.

    1,回退事務

    當執行DML操作修改數據時,UNDO數據被存放到UNDO,而新數據則被存放到數據段中,如果事務操作存在問題,舊需要回退事務,以取消事務變化.假定用戶A執行了語句UPDATE emp SET sal=1000 WHERE empno=7788后發現,應該修改雇員7963的工資,而不是雇員7788的工資,那么通過執行ROLLBACK語句可以取消事務變化.當執行ROLLBACK命令時,oracle會將UNDO段的UNDO數據800寫回的數據段中.

    2,讀一致性

    用戶檢索數據庫數據時,oracle總是使用用戶只能看到被提交過的數據(讀取提交)或特定時間點的數據(SELECT語句時間點).這樣可以確保數據的一致性.例如,當用戶A執行語句UPDATE emp SET sal=1000 WHERE empno=7788,UNDO記錄會被存放到回滾段中,而新數據則會存放到EMP段中;假定此時該數據尚未提交,并且用戶B執行SELECT sal FROM emp WHERE empno=7788,此時用戶B將取得UNDO數據800,而該數據正是在UNDO記錄中取得的.

    3,事務恢復

    事務恢復是例程恢復的一部分,它是由oracle server自動完成的.如果在數據庫運行過程中出現例程失敗(如斷電,內存故障,后臺進程故障等),那么當重啟oracle server,后臺進程SMON會自動執行例程恢復,執行例程恢復時,oracl會重新做所有未應用的記錄.回退未提交事務.

    4,倒敘查詢(FlashBack Query)

    倒敘查詢用于取得特定時間點的數據庫數據,它是9i新增加的特性,假定當前時間為上午11:00,某用戶在上午10:00執行UPDATE emp SET sal=3500 WHERE empno=7788語句,修改并提交了事務(雇員原工資為3000),為了取得10:00之前的雇員工資,用戶可以使用倒敘查詢特征.

    使用UNDO參數

    1,UNDO_MANAGEMENT

    該初始化參數用于指定UNDO數據的管理方式.如果要使用自動管理模式,必須設置該參數為AUTO,如果使用手工管理模式,必須設置該參數為MANUAL,使用自動管理模式時,oracle會使用undo表空間管理undo管理,使用手工管理模式時,oracle會使用回滾段管理undo數據,

    需要注意,使用自動管理模式時,如果沒有配置初始化參數UNDO_TABLESPACE,oracle會自動選擇第一個可用的UNDO表空間存放UNDO數據,如果沒有可用的UNDO表空間,oracle會使用SYSTEM回滾段存放UNDO記錄,并在ALTER文件中記載警告.

    2,UNDO_TABLESPACE

    該初始化參數用于指定例程所要使用的UNDO表空間,使用自動UNDO管理模式時,通過配置該參數可以指定例程所要使用的UNDO表空間.

    RAC(Real Application Cluster)結構中,因為一個UNDO表空間不能由多個例程同時使用,所有必須為每個例程配置一個獨立的UNDO表空間.

    3,UNDO_RETENTION

    該初始化參數用于控制UNDO數據的最大保留時間,其默認值為900,9i開始,通過配置該初始化參數,可以指定undo數據的保留時間,從而確定倒敘查詢特征(Flashback Query)可以查看到的最早時間點.

    建立UNDO表空間,

    UNDO表空間專門用于存放UNDO數據,并且在UNDO表空間尚不能建立任何數據對象(,索引,)

    1,使用CREATE DATABASE命令建立UNDO表空間.

    當使用CREATE DATABASE命令建立數據庫時,通過指定UNDO TABLESPACE選項,可以建立UNDO表空間.示例如下:

    CREATE DATABASE db01

    UNDO TABLESPACE undotbs_01

    DATAFILE ‘/u01/oracle/rbdb1/undo0101.dbf’ SIZE 30M;

    注意:UNDO TABLESPACE 子句不是必須的,如果使用自動UNDO管理模式,并且沒有指定該子句,那么建立數據庫時會自動生成名為SYS_UNDOTBSUNDO表空間.

    2,使用CREATE UNDO TABLESPACE命令建立UNDO表空間.

    CREATE UNDO TABLESPACE undotbs3

    DATAFILE ‘D:demoundotbs3.dbf’ SIZE 10M;

    修改UNDO表空間,

    使用ALTER TABLESPACE命令修改UNDO表空間.

    當事務用盡了UNDO表空間后,使用ALTER TABLESPACE … ADD DATAFILE增加數據文件

    UNDO表空間所在的磁盤填滿是,使用ALTER TABLESPACE … RENAME DATAFIEL 命令移動數據文件到其他磁盤上.

    使用ALTER DATABASE … OFFLINE/ONLINE使表空間脫機/聯機.

    當數據庫處于ARCHIVELOG模式時,使用ALTER TABLESPACE …BEGIN BACKUP/END BACKUP命令備份UNDO表空間.

    切換UNDO表空間.

    啟動例程并打開數據庫后,同一時刻特定例程只能使用一個UNDO表空間,切換UNDO表空間是指停止例程當前使用的UNDO表空間,并啟動其他UNDO表空間,下面以啟用undotbs2表空間為例,說明切換UNDO表空間的方法.

    ALTER SYSTEM SET undo_tablespace=undotbs02;

    RAC(Real Application Cluster)機構中,不同例程必須使用獨立的UNDO表空間,而不能共用同一個UNDO表空間.

    刪除UNDO表空間.

    當前例程正在使用的UNDO表空間是不能被刪除的,如果確定要刪除當前例程正在使用的UNDO表空間,應首先切換UNDO表空間.然后刪除相應的UNDO表空間.

    DROP TABLESPACE undotbs3;

    1,確定當前例程正在使用的UNDO表空間.

    Show parameter undo_tablespace

    2,顯示數據庫的所有UNDO表空間.

    SELECT tablespace_name FROMdba_tablespaces WHERE contents=’UNDO’;

    3,顯示UNDO表空間統計信息.

    使用自動UNDO管理模式時,需要合理地設置UNDO表空間的尺寸,為例合理規劃UNDO表空間尺寸,應在數據庫運行的高峰階段搜集UNDO表空間的統計信息.最終根據該統計信息確定UNDO表空間的尺寸.通過查詢動態性能視圖V%UNDOSTAT,可以搜集UNDO統計信息.

    SELECT TO_CHAR(BEGIN_TIME,’HH24:MI:SS’) BEGIN_TIME,

    TO_CHAR(END_TIME,’HH24:MI:SS’) END_TIME,

    UNDOBLKS

    FROM V$UNDOSTAT;

    BEGIN_TIME用于標識起始統計時間,END_TIME用于標識結束統計時間,UNDOBLKS用于標識UNDO數據所占用的數據塊個數.oracle每隔10分鐘生成一行統計信息.

    4,顯示UNDO段統計信息.

    使用自動UNDO管理模式時,oracle會在UNDO表空間上自動建立10UNDO,通過查詢動態信息視圖V$ROLLNAME,可以顯示所有聯機UNDO段的名稱,通過查詢動態性能視圖V$ROLLLISTAT,可以顯示UNDO段的統計信息.通過在V$ROLLNAMEV$ROLLLISTAT之間執行連接查詢,可以監視特定UNDO段的特定信息.

    SELECT a.name, b.xacts, b.writes, b.extents

    FROM v$rollname a, v$rollstat b

    WHERE a.usn=b.usn;

    Name用于標識UNDO段的名稱,xacts用于標識UNDO段所包含的活動事務個數,

    Writes用于標識在undo段上所寫入的字節數,extents用于標識UNDO段的區個數.

    5,顯示活動事務信息.

    當執行DML操作時,oracle會將這些操作的舊數據放到UNDO段中,動態性能視圖v$session用于顯示會話的詳細信息,動態性能視圖v$transaction用于顯示事務的詳細信息,動態性能視圖v$rollname用于顯示聯機UNDO段的名稱.通過在這3個動態性能視圖之間執行連接查詢,可以確定正在執行事務操作的會話,事務所使用的UNDO,以及事務所占用的UNDO塊個數.

    Col username format a10

    Col name format a10

    SELECT a.username, b.name, c.used_ublk

    FROM v$session a, v$rollname b, v$transaction c

    WHERE a.saddr=c.ses_addr AND b.usn=c.xidusn

    AND a.username=’SCOTT’;

    6,顯示UNDO區信息

    數據字典視圖dba_undo_extents用于顯示UNDO表空間所有區的詳細信息.包括UNDO區尺寸和狀態等信息.

    SELECT extend_id, bytes, status FROM dba_undo_extents

    WHERE segment_name’_SYSSMU5$’;

    其中,extent_id用于標識區編號,bytes用于標識區尺寸,status用于標識區狀態(ACTIVE:表示該區處于活動狀態,EXPIRED:標識該區未用).


    posted @ 2007-04-03 10:52 john 閱讀(1060) | 評論 (0)編輯 收藏

    修改oracle監聽占用的8080端口

    sqlplus /nolog
    ?
    SQL*Plus: Release 9.2.0.4.0 - Production on Sat Aug 6 14:24:49 2005
    ?
    Copyright (c) 1982, 2002, Oracle Corporation.? All rights reserved.
    ?
    SQL> connect / as sysdba;
    Connected.
    -- 把HTTP/WEBDAV端口從8080改到8081
    SQL> call dbms_xdb.cfg_update(updateXML(dbms_xdb.cfg_get(),
    ? 2? '/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()',8081))
    ? 3? /
    ?
    Call completed.
    -- 把FTP端口從2100改到2111
    SQL>? call dbms_xdb.cfg_update(updateXML(dbms_xdb.cfg_get(),
    ? 2? '/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()',2111))
    ? 3? /
    ?
    Call completed.
    ?
    SQL> commit;
    ?
    Commit complete.
    ?
    SQL>? exec dbms_xdb.cfg_refresh;
    ?
    PL/SQL procedure successfully completed.
    -- 檢查修改是否已經成功
    SQL> select dbms_xdb.cfg_get from dual;
    ?
    CFG_GET
    --------------------------------------------------------------------------------
    <xdbconfig xmlns="http://xmlns.oracle.com/xdb/xdbconfig.xsd" xmlns:xsi="http://w
    ?

    posted @ 2007-03-21 19:41 john 閱讀(763) | 評論 (0)編輯 收藏

    用Linux構建最好的FTP服務器

    用Linux構建最好的FTP服務器


    2005-01-10 15:03:32 來自:http://www.zhcedu.com.cn
    在眾多網絡應用中,FTP(文件傳輸協議)有著非常重要的地位。Internet中一個十分重
    要的資源就是軟件資源,而各種各樣的軟件資源大多數都放在FTP服務器中。與大多數
    Internet服務一樣,FTP也是一個客戶機/服務器系統。用戶通過一個支持FTP協議的客戶
    機程序,連接到主機上的FTP服務器程序。用戶通過客戶機程序向服務器程序發出命令,
    服務器程序執行用戶發出的命令,并將執行結果返回給客戶機。FTP服務可以根據服務對
    象的不同分為兩類:系統FTP服務器只允許系統上的合法用戶使用;匿名FTP服務器
    (Anonymous FTP Server)允許任何人登錄到FTP服務器去獲取文件。

    FTP的數據傳輸模式針對FTP數據連接而言,分為主動傳輸模式、被動傳輸模式和單端口傳
    輸模式三種。

    1.主動傳輸模式
    當FTP的控制連接建立,客戶提出目錄列表、傳輸文件時,客戶端發出PORT命令與服務器
    進行協商,FTP服務器使用一個標準端口20作為服務器端的數據連接端口(ftp-data),
    與客戶建立數據連接。端口20只用于連接源地址是服務器端的情況,并且端口20沒有監聽
    進程來監聽客戶請求。

    在主動傳輸模式下,FTP的數據連接和控制連接方向相反,由服務器向客戶端發起一個用
    于數據傳輸的連接。客戶端的連接端口由服務器端和客戶端通過協商確定。

    2.被動傳輸模式
    當FTP的控制連接建立,客戶提出目錄列表、傳輸文件時,客戶端發送PASV命令使服務器
    處于被動傳輸模式,FTP服務器等待客戶與其聯系。FTP服務器在非20端口的其它數據傳輸
    端口上監聽客戶請求。

    在被動傳輸模式下,FTP的數據連接和控制連接方向一致,由客戶端向服務器發起一個用
    于數據傳輸的連接。客戶端的連接端口是發起該數據連接請求時使用的端口。當FTP客戶
    在防火墻之外訪問FTP服務器時,需要使用被動傳輸模式。

    3.單端口模式
    除上述兩種模式之外,還有一種單端口模式。該模式的數據連接請求由FTP服務器發起。
    使用該傳輸模式時,客戶端的控制連接端口和數據連接端口一致。因為這種模式無法在短
    時間連續輸入數據、傳輸命令,因此并不常用。

    Linux下有很多可用的FTP服務器,其中比較流行的有WU-FTP(Washington University
    FTP)和VSFTP。Red Hat 8.0中自帶了WU-FTP和VSFTP兩個軟件。WU-FTP是一個著名的FTP
    服務器軟件,它功能強大,能夠很好地運行于眾多Unix操作系統中。不過作為后起之秀的
    VSFTP越來越流行,在Red Hat 9.0發行版中就只帶有VSFTP。

    VSFTP中VS的意思是“Very Secure”。從名稱可以看出,從一開始,軟件的編寫者就非常注
    重其安全性。除與生俱來的安全性外,VSFTP還具有高速、穩定的性能特點。在穩定性方
    面,VSFTP可以在單機(非集群)上支持4000個以上的并發用戶同時連接。據
    ftp.redhat.com的數據,VSFTP最多可以支持15000個并發用戶。

    快速構建FTP服務器

    FTP服務器實現的基本功能是上傳下載,下面就分幾個步驟來搭建一個可以實現下載功能
    的簡易FTP服務器。

    1.安裝FTP服務器
    如果在安裝系統時沒有選擇安裝FTP服務器,可以通過Red Hat 9.0中的“添加/刪除應用程
    序”工具進行安裝。具體方法是,選擇“主選單”→“系統設置”→“添加/刪除應用程序”,在彈
    出的界面中選中FTP服務器,單擊“更新”即可。

    如果無法確認是否安裝了該軟件,可以使用以下命令查看:

    #rpm -qa|grep vsftpd
    vsftpd-1.1.3-8

    2.啟動FTP服務器
    套用Red Hat 9.0的預設范例直接啟動VSFTP。
    # /sbin/service vsftpd start


    為vsftpd啟動vsftpd: [確定]

    3.在/var/ftp/pub目錄下創建一個名為test.txt的文件,文件內容為“This is a test
    file”。

    4.測試
    使用FTP客戶端登錄到本地服務器,然后以匿名身份(anonymous)登錄:

    # ftp 127.0.0.1
    Connected to 127.0.0.1 (127.0.0.1).
    220 (vsFTPd 1.1.3)
    Name (127.0.0.1:root): anonymous
    331 Please specify the password.
    Password:
    230 Login successful. Have fun.
    Remote system type is UNIX.
    Using binary mode to transfer files.

    這樣就成功地登錄到FTP服務器。可以顯示服務器目錄列表如下:

    ftp> ls
    227 Entering Passive Mode (127,0,0,1,63,15)
    drwxr-xr-x 2 0 0 4096 Dec 04 01:35 pub
    226 Directory send OK.

    切換到pub目錄下,并顯示目錄內容,可以找到剛才創建的文件test.txt:

    ftp> cd pub
    250 Directory successfully changed.
    ftp> ls
    227 Entering Passive Mode (127,0,0,1,232,34)
    150 Here comes the directory listing.
    -rw-r--r-- 1 0 0 21 Dec 04 01:35 test.txt
    226 Directory send OK.

    下載test.txt文件:

    ftp> mget test.txt
    mget test.txt? y
    227 Entering Passive Mode (127,0,0,1,186,210)
    150 Opening BINARY mode data connection for test.txt (21 bytes).
    226 File send OK.
    21 bytes received in 0.0108 secs (1.9 Kbytes/sec)

    查看本機目錄內容,可以看到test.txt已成功下載到本機。

    ftp> !ls
    a EIO_Binders initrd mnt proc tftpboot ylg.txt
    bin etc lib mymnt root tmp
    boot home lost+found myshare sbin usr
    dev id_dsas.pub misc opt test.txt var

    嘗試上傳名為ylg.txt的文件,可以看到請求被拒絕了。

    ftp> put ylg.txt
    local: ylg.txt remote: ylg.txt
    227 Entering Passive Mode (127,0,0,1,243,10)
    550 Permission denied.

    退出登錄:

    ftp> bye
    221 Goodbye.

    由測試可以看出,已經可以下載文件,但不能上傳文件(也不能在服務器上創建目錄和文
    件)。實際上這是一個專門提供下載服務的匿名FTP服務器。

    從上面的步驟可以看出,并不需要做什么配置就可以完成一個簡易FTP服務器的架設。這
    是因為Red Hat已經配置好一個缺省的FTP服務器。不過在實際應用中,大部分情況下這個
    簡易的服務器并不能滿足需求。

    進一步配置FTP服務器

    下面將創建一個能夠滿足常用需求的FTP服務器。實際應用中,FTP服務器一般要同時提供
    上傳和下載功能。此外,出于安全考慮,還需要有用戶身份驗證、用戶權限設置及空間管
    理等。下面就來搭建這樣一個FTP服務器。

    1.創建歡迎語。如果希望使用者在進入目錄時,能夠看到歡迎語或對本目錄的介紹,可
    以通過以下方法來實現。

    確定/etc/vsftpd/vsftpd.conf文件中dirmessage_enable=YES,默認情況下,Red Hat
    9.0有此設置。接著,在目錄中新增名為.message的文件。本例在/home/ylg目錄下創建一
    個.message文件,其內容為“歡迎來到我的FTP站點”。

    2.更換FTP服務器的默認端口。將預設的21端口改為2121,這樣做是基于安全的考慮。更
    改方法為,使用vi打開/etc/vsftpd/vsftpd.conf:
    #vi /etc/vsftpd/vsftpd.conf

    在文件最后增加如下一行內容:
    listen_port=2121

    3.取消anonymous登錄的功能。在vsftpd.conf文件中找到如下一行,并將其值改為“NO”:
    anonymous_enable=YES

    4.設定使用者不得更改目錄。這樣做的目的也是基于安全性的考慮。一般情況下,使用
    者的預設目錄為/home/username。若是不希望使用者在登錄后能夠切換至上一層目錄
    /home,則可通過以下設置來實現。在/etc/vsftpd/vsftpd.conf文件中找到以下三行內容:

    #chroot_list_enable=YES
    # (default follows)
    #chroot_list_file=/etc/vsftpd.chroot_list

    將其改為:

    chroot_list_enable=YES
    # (default follows)
    chroot_list_file=/etc/vsftpd/chroot_list

    新增一個文件/etc/vsftpd/chroot_list,文件內容為兩個用戶名:

    ylg
    user1

    5.針對不同的使用者限制不同的速度。假設用戶ylg所能使用的最高速度為500Kb/s,用
    戶user1所能使用的最高速度為250Kb/s,可以通過以下方法設置。在
    /etc/vsftpd/vsftpd.conf文件尾部新增以下一行:
    user_config_dir=/etc/vsftpd/userconf
    增加一個名為/etc/vsftpd/userconf的目錄:
    #mkdir /etc/vsftpd/userconf

    在/etc/vsftpd/userconf下新增一個名為ylg的文件,其內容如下所示:
    local_max_rate=500000

    在/etc/vsftpd/userconf目錄下新增一個名為user1的文件,其內容如下所示:
    local_max_rate=250000

    VSFTP對于速度的限制范圍大概在80%到120%之間,也就是限制最高速度為100Kb/s,但
    實際的速度可能在80Kb/s到120Kb/s之間。如果頻寬不足,數值會低于此限制。

    6.對于每一個聯機用戶,都以獨立的進程來運行。一般情況下,在啟動VSFTP時,只會看
    到一個名為vsftpd的進程在運行。但若是讀者希望每一個聯機用戶都能以獨立的進程來呈
    現,則可通過在/etc/vsftpd/vsftpd.conf文件中增加以下一行來實現:
    setproctitle_enable=YES

    7.保存/etc/vsftpd/vsftpd.conf文件,然后重新啟動vsftpd:
    #service vsftpd restart

    8.測試剛創建的FTP服務器。
    以缺省方式登錄會被拒絕,因為此時的默認端口號已經更改為2121,所以登錄時需指定端
    口。

    # ftp 127.0.0.1
    ftp: connect: Connection refused

    此時也不能再使用匿名方式登錄:

    # ftp 127.0.0.1 2121
    Connected to 127.0.0.1 (127.0.0.1).
    220 (vsFTPd 1.1.3)
    Name (127.0.0.1:root): anonymous
    331 Please specify the password.
    Password:
    530 Login incorrect.
    Login failed.

    如果以用戶ylg則可以成功登錄(指定端口2121),并顯示歡迎信息:

    # ftp 127.0.0.1 2121
    Connected to 127.0.0.1 (127.0.0.1).
    220 (vsFTPd 1.1.3)
    Name (127.0.0.1:root): ylg
    331 Please specify the password.
    Password:
    230-歡迎來到我的FTP站點
    230 Login successful. Have fun.
    Remote system type is UNIX.
    Using binary mode to transfer files.

    因為在設置中設定了不能切換目錄,所以下列命令無法正確執行:

    ftp> cd /home
    550 Failed to change directory.

    再來測試一下上傳和下載。首先下載服務器目錄中的test.txt文件:

    ftp> get test.txt
    local: test.txt remote: test.txt
    227 Entering Passive Mode (127,0,0,1,243,215)
    150 Opening BINARY mode data connection for test.txt (21 bytes).
    226 File send OK.
    21 bytes received in 0.00308 secs (6.7 Kbytes/sec)

    可以通過!ls命令看到本機目錄中已成功下載該文件。然后上傳本機目錄中的ylg.txt文件
    到服務器:

    ftp> put ylg.txt
    local: ylg.txt remote: ylg.txt
    227 Entering Passive Mode (127,0,0,1,133,248)
    150 Ok to send data.
    226 File receive OK.
    19 bytes sent in 0.0401 secs (0.46 Kbytes/sec)

    用ls命令查看服務器目錄,會發現該文件已成功上傳。

    為了測試不同連機用戶使用的是不同進程,可以使用ps -ef指令,顯示如下所示:

    # ps -ef|grep ftp
    root 12972 1356 0 13:44 pts/1 00:00:00 ftp 127.0.0.1 2121
    nobody 12973 12908 0 13:44 ? 00:00:00 [vsftpd]
    ylg 12975 12973 0 13:44 ? 00:00:00 [vsftpd]
    user1 13013 13011 0 13:46 ? 00:00:00 [vsftpd]
    root 13041 13015 0 13:47 pts/4 00:00:00 grep ftp

    到現在為止,一個基本可以滿足普通使用需求的FTP服務器就已經架設完成。

    在實際應用中,有時為了增加安全性,會將FTP服務器置于防火墻之后。如本文開頭所
    述,被動傳輸模式適合于帶有防火墻的情況。下面就來創建一個防火墻后的FTP服務器,
    該服務器FTP端口為2121,數據傳輸端口為2020。

    執行以下兩行指令,只允許2121和2020端口打開,其余端口關閉:

    #iptables -A INPUT -p tcp -m multiport --dport 2121,2020 -j ACCEPT
    #iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset

    修改/etc/vsftpd/vsftpd.conf文件,在文本最后添加以下兩行:

    listen_port=2121
    ftp_data_port=2020

    重新啟動vsftpd:
    #service vsftpd restart

    有時希望直接在/etc/hosts.allow中定義允許或拒絕某一源地址,可以通過以下配置來實
    現。先確保/etc/vsftpd/vsftpd.conf中tcp_wrappers=YES,Red Hat 9.0中,這是默認
    值。重新啟動vsftpd:
    #service vsftpd restart

    假設提供168.192.2.1和210.31.8.1到210.31.8.254的連接,則可對/etc/hosts.allow進
    行如下設定:

    vsftpd : 168.192.2.1 210.31.8. : allow
    ALL : ALL : DENY

    配置虛擬用戶FTP

    上面配置的FTP服務器有一個特點,就是FTP服務器的用戶本身也是系統用戶。這顯然是一
    個安全隱患,因為這些用戶不僅能夠訪問FTP,也能夠訪問其它的系統資源。如何解決這
    個問題呢?答案就是創建一個虛擬用戶的FTP服務器。虛擬用戶的特點是只能訪問服務器
    為其提供的FTP服務,而不能訪問系統的其它資源。所以,如果想讓用戶對FTP服務器站內
    具有寫權限,但又不允許訪問系統其它資源,可以使用虛擬用戶來提高系統的安全性。

    在VSFTP中,認證這些虛擬用戶使用的是單獨的口令庫文件(pam_userdb),由可插入認
    證模塊(PAM)認證。使用這種方式更加安全,并且配置更加靈活。 下面介紹配置過程。

    1.生成虛擬用戶口令庫文件。為了建立此口令庫文件,先要生成一個文本文件。該文件
    的格式如下,單數行為用戶名,偶數行為口令:

    #vi account.txt
    ylg
    1234
    zhanghong
    4321
    gou
    5678

    2.生成口令庫文件,并修改其權限:

    #db_load -T -t hash -f ./account.txt /etc/vsftpd/account.db
    #chmod 600 /etc/vsftpd/account.db

    3.新建一個虛擬用戶的PAM文件。加上如下兩行內容:

    #vi /etc/pam.d/vsftp.vu
    auth required /lib/security/pam_userdb.so db=/etc/vsftpd/account
    account required /lib/security/pam_userdb.so db=/etc/vsftpd/account

    4.建立虛擬用戶,設置該用戶所要訪問的目錄,并設置虛擬用戶訪問的權限:

    #useradd -d /ftpsite virtual_user
    #chmod 700 /ftpsite

    經過該步驟的設置,/ftpsite就是virtual_user用戶的主目錄,該用戶也是/ftpsite目錄
    的擁有者。除root用戶之外,只有該用戶具有對該目錄的讀、寫和執行的權限。

    5.生成一個測試文件。先切換至virtual_user用戶身份,然后在/ftpsite目錄下創建一
    個文件:

    #su -virtual_user
    $vi /ftpsite/mytest
    This is a test file.
    $su - root

    6.編輯/etc/vsftpd/vsftpd.conf文件,使其整個文件內容如下所示(去掉了注釋內容):

    anonymous_enable=NO
    local_enable=YES
    local_umask=022
    xferlog_enable=YES
    connect_from_port_20=YES
    xferlog_std_format=YES
    listen=YES
    write_enable=YES
    anon_upload_enable=YES
    anon_mkdir_write_enable=YES
    anon_other_write_enable=YES
    one_process_model=NO
    chroot_local_user=YES
    ftpd_banner=Welcom to my FTP server.
    anon_world_readable_only=NO
    guest_enable=YES
    guest_username=virtual_user
    pam_service_name=vsftp.vu

    上面代碼中,guest_enable=YES表示啟用虛擬用戶;guest_username=virtual則是將虛擬
    用戶映射為本地用戶,這樣虛擬用戶登錄后才能進入本地用戶virtual的目錄/ftpsite;
    pam_service_name=vsftp.vu指定PAM的配置文件為vsftp.vu。

    7.重新啟動VSFTP:
    #service vsftpd restart

    8.以虛擬用戶gou(Linux中并無該賬號)進行測試:

    # ftp 127.0.0.1
    Connected to 127.0.0.1 (127.0.0.1).
    220 Welcom to my FTP server.
    Name (127.0.0.1:root): gou
    331 Please specify the password.
    Password:
    230 Login successful. Have fun.
    Remote system type is UNIX.
    Using binary mode to transfer files.

    測試下載服務器目錄中的一個文件mytest:

    ftp> get mytest
    local: mytest remote: mytest
    227 Entering Passive Mode (127,0,0,1,159,19)
    150 Opening BINARY mode data connection for mytest (21 bytes).
    226 File send OK.
    21 bytes received in 0.00038 secs (54 Kbytes/sec)

    測試上傳本機目錄中的文件vsftpd.conf:

    ftp> !ls
    account.db chroot_list k mytest userconf vsftpd.conf
    ftp> put vsftpd.conf
    local: vsftpd.conf remote: vsftpd.conf
    227 Entering Passive Mode (127,0,0,1,117,203)
    150 Ok to send data.
    226 File receive OK.
    4229 bytes sent in 0.00195 secs (2.1e+03 Kbytes/sec)

    可以看到,使用沒有系統賬號的虛擬用戶可以成功完成上傳、下載的工作。但該FTP虛擬
    服務器只允許虛擬用戶登錄,其它系統用戶無法登錄,如系統用戶user1不是虛擬用戶,
    則不能登錄該虛擬服務器。

    # ftp 127.0.0.1
    Connected to 127.0.0.1 (127.0.0.1).
    220 Welcom to my FTP server.
    Name (127.0.0.1:root): user1
    331 Please specify the password.
    Password:
    530 Login incorrect.
    Login failed.

    在虛擬FTP服務器中,也可以對各個用戶的權限進行設置。方法是在/etc/vsftpd.conf文
    件中添加如下一行:
    user_config_dir=用戶配置文件目錄

    然后在用戶配置文件目錄下創建相應的用戶配置文件,比如為上述名為gou的用戶創建一
    個配置文件(假設配置文件目錄為/etc/user_config_dir):

    #vi /etc/user_config_dir/gou
    write_enable=NO
    anono_upload_enable=NO

    重啟FTP服務器,這時再使用賬號gou來登錄,就已經沒有上傳的權限了。

    posted @ 2006-12-26 22:37 john 閱讀(428) | 評論 (0)編輯 收藏

    更改Oracle的默認監聽端口 1521

    如何更改Oracle的默認監聽端口(1521)
    Oracle 的默認監聽端口為1521,你可以方便的依照下列步驟修改為其他端口:
    [oracle@dbserver2 admin]$ cd $ORACLE_HOME/network/admin
    [oracle@dbserver2 admin]$ vi listener.ora
    修改這個文檔中的1521端口為你需要的端口your port
    [oracle@dbserver2 admin]$ lsnrctl stop
    [oracle@dbserver2 admin]$ lsnrctl start
    修改客戶端的連接

    posted @ 2006-12-26 22:05 john 閱讀(4180) | 評論 (0)編輯 收藏

    修改 Oracle9i 8080端口問題

    修改 Oracle9i 8080端口問題

    Oracle 9i開始,創建數據庫時默認包含了XDB特性。一旦啟動了數據庫和Listener,Oracle XDB的http服務就占用8080端口,剛好和JBoss、Tomcat等默認端口沖突。除了修改Tomcat等外,還可以修改XDB的配置。
    Oracle XDB的端口設置不在配置文件中,而是在數據庫里。修改XDB的http和ftp服務端口的方法有3種:

    1.使用sys登錄Oracle,利用dbms_xdb修改端口設置

    ? SQL> -- Change the HTTP/WEBDAV port from 8080 to 8081
    ? SQL> call dbms_xdb.cfg_update(updateXML(
    ??? 2??????? dbms_xdb.cfg_get()
    ??? 3????? , '/xdbconfig/sysconfig/protocolconfig/httpconfig/http-port/text()'
    ??? 4????? , 8081))
    ??? 5? /

    ? Call completed.


    ? SQL> -- Change the FTP port from 2100 to 2111
    ? SQL> call dbms_xdb.cfg_update(updateXML(
    ??? 2???????? dbms_xdb.cfg_get()
    ??? 3?????? , '/xdbconfig/sysconfig/protocolconfig/ftpconfig/ftp-port/text()'
    ??? 4?????? , 2111))
    ??? 5? /

    ? Call completed.


    ? SQL> COMMIT;

    ? Commit complete.


    ? SQL> EXEC dbms_xdb.cfg_refresh;

    ? PL/SQL procedure successfully completed.


    2.使用OEM console,選擇數據庫,XML Database,Configuration。更改XDB的有關設置。

    3.去掉數據庫的初始化參數:? dispatchers='(PROTOCOL=TCP) (SERVICE=XDB)',將會禁止XDB的http和ftp服務。

    posted @ 2006-12-26 21:59 john 閱讀(390) | 評論 (0)編輯 收藏

    PCC-S-02014, Encountered the symbol "..." when expecting one of the following:

    proc cpp_suffix=cpp code=cpp txsPublic.pcc define=__linux UNSAFE_NULL=YES MODE=ORACLE DBMS=V8 CHAR_MAP=STRING INCLUDE=/home/tax/100/src/public/include INCLUDE=/home/tax/100/src/server/include INCLUDE=/usr/oracle/product/9.2.0/precomp/public

    Pro*C/C++: Release 9.2.0.6.0 - Production on Fri Nov 24 17:07:54 2006
    Syntax error at line 52, column 37, file /usr/include/c++/3.4.3/bits/concept_check.h:
    Error at line 52, column 37 in file /usr/include/c++/3.4.3/bits/concept_check.h
    #define __glibcxx_function_requires(...)
    ....................................1
    PCC-S-02014, Encountered the symbol "..." when expecting one of the following:

    ?? ) an identifier, define, elif, else, endif, error, if, ifdef,
    ?? ifndef,
    解決方法:
    1、配置好?$ORACLE_HOME/precomp/admin/pcscfg.cfg?文件
    ???根據你的系統不同,大概像這樣

    				
    sys_include=(/usr/lib/gcclib/i386redhatlinux/3.2.2/include,/u01/oracle/product/8.1.7/precomp/public,/usr/include,/usr/include/sys)
    include=(/u01/oracle/product/8.1.7/precomp/public)
    include=/u01/oracle/product/8.1.7/precomp/hdrs
    include=/u01/oracle/product/8.1.7/tpcc2x_2/src
    include=/u01/oracle/product/8.1.7/precomp/precomp/include
    include=/u01/oracle/product/8.1.7/precomp/oracore/include
    include=/u01/oracle/product/8.1.7/precomp/oracore/public
    include=/u01/oracle/product/8.1.7/precomp/rdbms/include
    include=/u01/oracle/product/8.1.7/precomp/rdbms/public
    include=/u01/oracle/product/8.1.7/precomp/rdbms/demo
    include=/u01/oracle/product/8.1.7/precomp/nlsrtl/include
    include=/u01/oracle/product/8.1.7/precomp/nlsrtl/public
    include=/u01/oracle/product/8.1.7/precomp/network_src/include
    include=/u01/oracle/product/8.1.7/precomp/network_src/public
    include=/u01/oracle/product/8.1.7/precomp/network/include
    include=/u01/oracle/product/8.1.7/precomp/network/public
    include=/u01/oracle/product/8.1.7/precomp/plsql/public
    ltype=short


    ???
    2、預編譯的時候加上?parse=none?選項
    ????proc?iname=***??parse=none

    3、編譯的時候要鏈接oracle的庫文件,?加選項?-lclntsh
    ?????下面是我參照別的網友的一個makefile文件,
    ???

    INCLDIR=?-I.?-I/u01/oracle/product/8.1.7/precomp/public?-I/u01/oracle/product/8.1.7/rdbms/public?-I/u01/oracle/product/8.1.7/rdbms/demo?-I/u01/oracle/product/8.1.7/plsql/public?-I/u01/oracle/product/8.1.7/network/public?

    DFLAGS=?-DPRECOMP?-DLINUX?-D_GNU_SOURCE?-DSLTS_ENABLE?-DSLMXMX_ENABLE?-D_REENTRANT?-DNS_THREADS

    CFLAGS=?-O3

    LIBPATH=?-L/u01/oracle/product/8.1.7/lib/

    LIBS=-lclntsh?`cat?/u01/oracle/product/8.1.7/lib/sysliblist`?-ldl?-lm

    myproc:myproc.pc
    proc?parse=no?iname=myproc.pc?include=$(ORACLE_HOME)/precomp/public
    gcc??-o?$@?$@.c?-I$(ORACLE_HOME)/precomp/public?-L$(ORACLE_HOME)/lib?-lclntsh?-lclient8?$(LIBPATH)?$(LIBS)

    clean:
    rm?*.lis?myproc.c?myproc

    posted @ 2006-11-24 11:04 john 閱讀(11484) | 評論 (6)編輯 收藏

    單點登錄簡單實現

    單點登錄的簡單實現

      在門戶項目中,經常會遇到如何實現單點登錄的問題,下面就本人的經驗做個總結。歡迎大家進行補充討論。

    單點登錄的具體實現有很多種選擇,包括:

    1. 采用專門的SSO商業軟件: 主要有:Netgrity的Siteminder,已經被CA收購。Novell 公司的iChain。RSA公司的ClearTrust等。
    2. 采用門戶產品供應商自己的SSO產品,如:BEA的WLES,IBM 的Tivoli Access Manager,Sun 公司的identity Server,Oracle公司的OID等。
    3. 這些商業軟件一般適用于客戶對SSO的需求很高,并且企業內部采用COTS軟件如:Domino,SAP,Sieble的系統比較多的情況下采用。并結合身份管理。統一認證等項目采用。采用這些軟件一般都要對要集成的系統做些改造,如在要集成的系統上安裝AGENT。現在一般只提供常見軟件如:Domino,SAP,Sieble,常見應用服務器:weblogic,websphere等的AGENT。要先統一這些系統的認證。一般采用LDAP或數據庫。然后才能實現SSO。比較麻煩。
    4. 另外,如果不想掏銀子,也有OPEN SOURCE的SSO軟件可選:主要有:http://www.josso.org/https://opensso.dev.java.net/http://www.sourceid.org 等。具體怎么樣就不清楚了。

      如果項目對SSO的要求比較低,又不想對要被集成的系統做任何改動,可采用下面介紹的方式簡單實現:下面我們通過一個例子來說明。假如一個門戶項目要對下面的幾個系統做SSO。

    圖一

      用戶在這些系統中的用戶名,密碼各不相同,如:員工號為001的員工在這些系統中的用戶名,密碼分別如下:

    用戶 系統 用戶名 密碼
    001 Portal系統 A 1234
    001 郵件系統 B 2345
    001 DOMINO系統 C AAAA
    001 報銷系統 D CCCC
    001 工資系統 E BBBB

    首先,建立員工在PORTAL系統中的用戶名和其他系統中的用戶名之間的對應關系

      首先,要建立員工在PORTAL系統中的用戶名和其他系統中的用戶名之間的對應關系并保存。可保存在表中或LDAP中或文件系統中。當然要考慮這些系統之間的數據同步問題。比較好的方式是找到用戶在這些系統中的都存在的唯一信息(如員工號,MAIL地址,姓名等)。通過唯一信息實時到各個系統中去取認證所需要的信息。就不需要考慮數據同步問題。比較實用。可以建立類似下面的表:密碼可采用加密保存。如果是采用BEA的Weblogic Portal,可采用UUP來保存這些信息。

    	(
    	
    	user	 varchar2(20),   	/*用戶名*/
    	app_name varchar2(20),  	/*應用系統*/
    	architect varchar2(4),  		/*應用系統的架構BS或CS*/
    	app_company varchar2(50),          /*用戶所屬分公司*/
    	app_department varchar2(50),      /*用戶所在的部門*/
    	app_user varchar2(15),                 /*在該系統中的用戶名*/
    	app_passwd varchar2(15), 	/*在該系統中的密碼*/
    	app_cookie varchar2(30),              /*COOKIE名稱*/
    	form_user varchar2(20),                /*認證頁面中FORM的用戶名字段*/
    	form_passwd varchar2(20),          /*認證頁面中FORM的密碼字段*/
    	app_special  varchar2(20)           /*其他*/
    	);
    

    通過IFRAME或超連接方式集成目標系統,并進行SSO

      通過IFRAME或超連接方式集成目標系統,并在URL中帶上用戶名和密碼。如集成DOMINO可采用如下方式:

      <IFRAME src=http://host1/names.nsf?Login&Username=admin&Password=pass&RedirectTo=/names.nsf
    width="100%" frameborder="0" align="middle" height="100%" hspace="0" marginheight="0" marginwidth="0" scrolling="yes" style="background-color:#f7f7ff;">
    </IFRAME>

      或:
    Href src=“http:// host1/names.nsf?Login&Username=admin&Password=pass&RedirectTo=/names.nsf
    以上采用的是在HTTP中直接傳遞明碼,為提高安全性,可采用HTTPS來傳遞用戶名和密碼。另外采用這種方式被集成的系統必須支持FORM方式認證。J2EE應用,DOMINO等都支持FORM認證。

      這兩種方式如果SSO成功,就自動進入目標系統的界面,如果實現會顯示目標系統的登錄界面。其效果圖如下:

    登錄界面

      這種方式,必須維護對應關系表,如上面的sso_info。更好的方式是提供界面,讓最終用戶自己維護這種對應關系,可模仿Compoze portlets for lotus的做法,在用戶第一次進入要與之做SSO的系統時,如DOMINO系統,顯示一個界面,讓用戶自己輸入他在該系統中的用戶名/密碼等信息。并保存到表中或LDAP等其他數據源中。以后用戶要進入這些系統時,就直接從表中或其他數據源中取用戶的用戶名/密碼等信息,幫助用戶做認證。建議采用這種方式。如下圖所示。如果用戶改變了自己在DOMINO系統中的用戶名,密碼。從門戶系統進入DOMINO系統時,認證會失敗,就重新顯示類似下面的界面。讓用戶重新輸入他在DOMINO系統中新的用戶名,密碼并保存。

    認證失敗

      以上這種實現方式,一般需要瀏覽器支持COOKIE,所以要注意瀏覽器的配置,在開發階段,為方便調試,可設置IE,讓它顯示COOKIE的名稱。如下所示:

    瀏覽器的配置

      采用這種方式,對要集成的系統不需要做任何的改動。如果PORTAL系統中的用戶在被集成的系統中的權限都一樣,可采用建立一個通用用戶的做法。也就是所有在PORTAL系統中的用戶都采用這個通用用戶進入目標系統。這種方式等于是采用頁面集成方式做集成。比較方便使用。另外,有時候需要采用調用API,或配置Adapter等應用集成方式來集成其他系統,一般也是通過定義一個連接專用的用戶。在API中或在配置Adapter的時候寫死。如采用JAVA API方式集成DOMINO:

      lotus.domino.Session dominoSession = NotesFactory.createSession(dominoServer, “admin”, “password”);

    CS結構實現方式

      經常有人問CS結構的應用如何實現SSO,本人的建議是對這種系統不要自己去實現SSO。很麻煩,其實輸個用戶名,密碼沒什么大不了的。如果要實現,一是采用商業軟件。另外也可以采用以下方式:在PORTAL的PORTLET上建立超連接。并通過APPLET方式啟動CS結構的應用系統的登錄界面。然后通過如下的方式把用戶名/密碼傳遞過去。

      -不能做任何改動的客戶端 - WIN消息(給登錄窗口發送用戶名,密碼等登錄所需要的信息),模擬鍵盤(java有模擬鍵盤輸入的API)

      -可以做改動的客戶端 - 參數傳遞,并讓登錄的EXE文件讀取參數進行認證。

      因為要讓APPLET執行本地的EXE文件,所以必須對IE中的JRE的安全進行設置。

    對IE中的JRE的安全進行設置

    其他:

      在采用以上方式實現了SSO后,要注意LOGOUT,可采用與LOGIN相同的方式。也可以通過被集成系統的超時設置來實現。

    單點登錄SSO技術資料收集

    posted @ 2006-11-16 00:23 john 閱讀(747) | 評論 (0)編輯 收藏

    UUID

    對UUID幾乎沒有了解,google了一下,才知道是128位整數(16字節)的全局唯一標識符(Universally Unique Identifier)。
    UUID是指在一臺機器上生成的數字,它保證對在同一時空中的所有機器都是唯一的。通常平臺會提供生成UUID的API。UUID按照開放軟件基金會(OSF)制定的標準計算,用到了以太網卡地址、納秒級時間、芯片ID碼和許多可能的數字。由以下幾部分的組合:當前日期和時間(UUID的第一個部分與時間有關,如果你在生成一個UUID之后,過幾秒又生成一個UUID,則第一個部分不同,其余相同),時鐘序列,全局唯一的IEEE機器識別號(如果有網卡,從網卡獲得,沒有網卡以其他方式獲得),UUID的唯一缺陷在于生成的結果串會比較長。關于UUID這個標準使用最普遍的是微軟的GUID(Globals Unique Identifiers)。
    在ColdFusion中可以用CreateUUID()函數很簡單的生成UUID,其格式為:xxxxxxxx-xxxx-xxxx-xxxxxxxxxxxxxxxx(8-4-4-16),其中每個 x 是 0-9 或 a-f 范圍內的一個十六進制的數字。而標準的UUID格式為:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx (8-4-4-4-12)
    ,可以從cflib?下載CreateGUID() UDF進行轉換。
    使用UUID的好處在分布式的軟件系統中(比如:DCE/RPC, COM+,CORBA)就能體現出來,它能保證每個節點所生成的標識都不會重復,并且隨著WEB服務等整合技術的發展,UUID的優勢將更加明顯。
    關于UUID的更多信息可以多google?一下。

    posted @ 2006-11-16 00:18 john 閱讀(529) | 評論 (0)編輯 收藏

    主站蜘蛛池模板: 红杏亚洲影院一区二区三区| 久久精品国产亚洲av麻豆色欲| 国产精品永久免费| 国产亚洲婷婷香蕉久久精品| 1000部拍拍拍18勿入免费视频软件 | 亚洲AV成人精品网站在线播放| 亚洲三级高清免费| 深夜福利在线视频免费| 久久99亚洲网美利坚合众国| 国产成人免费永久播放视频平台| 国产无遮挡无码视频免费软件| 成人亚洲国产va天堂| 亚洲va久久久噜噜噜久久狠狠| 成年午夜视频免费观看视频| 亚洲日韩在线观看免费视频| 亚洲一欧洲中文字幕在线| 国产综合亚洲专区在线| 大陆一级毛片免费视频观看i| 丁香花在线视频观看免费| 久久国产乱子精品免费女| 亚洲人成网站色在线观看| 国产亚洲精品自在久久| 日韩免费三级电影| 6080午夜一级毛片免费看6080夜福利 | 亚洲人成伊人成综合网久久| 亚洲第一黄色网址| 成年女人18级毛片毛片免费| 亚洲精品免费观看| 久久精品成人免费国产片小草| 亚洲日韩精品国产3区| 久久国产亚洲电影天堂| 免费一级毛片清高播放| 无限动漫网在线观看免费| 七色永久性tv网站免费看| 一个人免费观看视频在线中文| 亚洲一卡一卡二新区无人区| 青青草原精品国产亚洲av| 国产午夜亚洲精品理论片不卡| 国产精品免费视频网站| 色婷婷7777免费视频在线观看| 99久久国产免费中文无字幕|