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

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

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

    java思維

    正在學習中:(

    2008年12月7日 #

    bcb6 中安裝 boost

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

    性能分析
    通過上面的討論,大家已經(jīng)了解到boost的強大威力,那個性能又如何呢?為此我們再實際來拆分一個
    復雜的html代碼,看看到底需要花費多少時間。
    為了節(jié)省篇幅,這里就不列出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的效率是非常高的,雖然與一些角本語言比起來解析速度還是慢,但已經(jīng)可以滿足大多數(shù)編程要求了。另外作者的計算機配置并不是非常高,相信拿到現(xiàn)在任何一臺主流配置的計算機上都會優(yōu)于作者的結果。
    結束語

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

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

    2008年5月25日 #

    RedHat LinuxAS4 cvs 服務器搭建步驟

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

     

    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

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

    4:用戶管理

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

    用戶名:密碼:系統(tǒng)用戶

    #htpasswd passwd username

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

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

    測試登陸

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

    ok

     

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

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

    代碼:
    Linux    Linux
    Kernel   Linux/kernel


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

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

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

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


    然后創(chuàng)建/home/cvsroot/cvs.run文件,該文件必須可執(zhí)行,內容格式為:

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


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

     

     

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

    2008年1月28日 #

    Oracle 內存分配建議


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

    首先不要迷信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,本人無這方面經(jīng)驗)

    下面是我的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 一類的使用了很多存儲過程函數(shù)、包 ,或者很大的系統(tǒng),可以考慮增大shared_pool_size ,但是如果超過500M可能是危險的,達到1G可能會造成CPU的嚴重負擔,系統(tǒng)甚至癱瘓。所以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 的緣故,這個時候依據(jù) session最大數(shù)量和 sort_ares_size 等參數(shù)設置,必須增大large_pool_size 的設置,可以考慮為 session * (sort_area_size + 2M)。這里要提醒一點,不是必須使用MTS,我們都不主張使用MTS,尤其同時在線用戶數(shù)小于500的情況下。

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

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

    還有2個重要參數(shù)我們需要注意

    sort_area_size and hash_area_size
    這兩個參數(shù)在非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

    物理內存再大已經(jīng)跟參數(shù)沒有關系了


    假定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



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


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

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

    2007年12月27日 #

    Oracle 回滾段空間回收步驟

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

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

    2007年12月26日 #

    常用的MQ命令

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

    創(chuàng)建隊列管理器
    crtmqm –q QMgrName
    -q是指創(chuàng)建缺省的隊列管理器

    刪除隊列管理器
    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環(huán)境中可以執(zhí)行的MQ命令(即在runmqsc環(huán)境下可以敲的命令)

    定義持久信隊列
    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

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

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

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

    創(chuàng)建服務器連接通道
    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                    轉換數(shù)據(jù)

    dmpmqaut                轉儲對象權限管理

    dmpmqlog                轉儲日志管理

    dspmq                         顯示隊列管理器

    dspmqaut                  顯示打開對象的權限

    dmpmqcap               顯示處理程序容量和處理程序數(shù)

    dspmqcsv                 顯示命令服務器狀態(tài)

    dspmqfls                   顯示文件名

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

    dspmqrtn                   顯示事務的詳細信息

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

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

    endmqtrc                   停止跟蹤

    rcdmqimg                  向日志寫對象的映像

    rcmqobj                      根據(jù)日志中的映像重新創(chuàng)建一個對象

    rsvmqtrn                     提交或逆序恢復事務

     


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

    2007年11月22日 #

    BCB UTF-8 格式轉換

    如果是字串轉換.BCB有多個方法(如TStringConverter,或API的 WideCharToMultiByte/MultiByteToWideChar,VCL的WideCharToString/StringToWideChar等)
    當然,BCB本身就支持三種字串,前兩種可自動轉,后一種有函數(shù):
    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)編輯 收藏

    2007年10月24日 #

    Oracle安裝的一些問題收集

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

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

    2007年7月23日 #

    東京愛情故事?

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

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

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

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

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

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

    Linux系統(tǒng)環(huán)境下的Socket編程詳細解析

    Linux系統(tǒng)環(huán)境下的Socket編程詳細解析

    什么是Socket

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

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

      Socket建立

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

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

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

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

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

      Socket配置

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

      

    int bind(int sockfd,struct sockaddr *my_addr, int addrlen); 
      Sockfd是調用socket函數(shù)返回的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 字節(jié)的協(xié)議地址 */
    };
      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()函數(shù)將其置為零。指向sockaddr_in 的指針和指向sockaddr的指針可以相互轉換,這意味著如果一個函數(shù)所需參數(shù)類型是sockaddr時,你可以在函數(shù)調用的時候將一個指向sockaddr_in的指針轉換為指向sockaddr的指針;或者相反。

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

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

      注意在使用bind函數(shù)是需要將sin_port和sin_addr轉換成為網(wǎng)絡字節(jié)優(yōu)先順序;而sin_addr則不需要轉換。

      計算機數(shù)據(jù)存儲有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先和低位字節(jié)優(yōu)先。Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡上傳輸,所以對于在內部是以低位字節(jié)優(yōu)先方式存儲數(shù)據(jù)的機器,在Internet上傳輸數(shù)據(jù)時就需要進行轉換,否則就會出現(xiàn)數(shù)據(jù)不一致。

      下面是幾個字節(jié)順序轉換函數(shù):

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

     

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

    連接建立

     

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

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

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

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

      int listen(int sockfd, int backlog);

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

      當出現(xiàn)錯誤時listen函數(shù)返回-1,并置相應的errno錯誤碼。

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

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

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

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

      數(shù)據(jù)傳輸

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

      Send()函數(shù)原型為:

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

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

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

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

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

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

      Recvfrom()函數(shù)原型為:

      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中的數(shù)據(jù)字節(jié)數(shù)。Recvfrom()函數(shù)返回接收到的字節(jié)數(shù)或當出現(xiàn)錯誤時返回

      1,并置相應的errno。

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

      結束傳輸

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

      close(sockfd);

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

      int shutdown(int sockfd,int how);

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

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

     面向連接的Socket實例

     

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

      該服務器軟件代碼如下:

    #include  
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #define SERVPORT 3333 /*服務器監(jiān)聽端口號 */
    #define BACKLOG 10 /* 最大同時連接請求數(shù) */
    main()
    {
    int sockfd,client_fd; /*sock_fd:監(jiān)聽socket;client_fd:數(shù)據(jù)傳輸socket */
     struct sockaddr_in my_addr; /* 本機地址信息 */
     struct sockaddr_in remote_addr; /* 客戶端地址信息 */
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
      perror("socket創(chuàng)建出錯!"); 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函數(shù)創(chuàng)建一個Socket,然后調用bind函數(shù)將其與本機地址以及一個本地端口號綁定,然后調用listen在相應的socket上監(jiān)聽,當accpet接收到一個連接服務請求時,將生成一個新的socket。服務器顯示該客戶機的IP地址,并通過新的socket向客戶端發(fā)送字符串"Hello,you are connected!"。最后關閉該socket。

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

      客戶端程序代碼如下:

    #include 
    #include
    #include
    #include
    #include
    #include
    #include
    #include
    #define SERVPORT 3333
    #define MAXDATASIZE 100 /*每次最大數(shù)據(jù)傳輸量 */
    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創(chuàng)建出錯!");
    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地址,然后創(chuàng)建一個socket,調用connect函數(shù)與服務器建立連接,連接成功之后接收從服務器發(fā)送過來的數(shù)據(jù),最后關閉socket。

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


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

     

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

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

      阻塞和非阻塞

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

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

      其中readfds、writefds、exceptfds分別是被select()監(jiān)視的讀、寫和異常處理的文件描述符集合。如果你希望確定是否可以從標準輸入和某個socket描述符讀取數(shù)據(jù),你只需要將標準輸入的文件描述符0和相應的sockdtfd加入到readfds集合中;numfds的值是需要檢查的號碼最高的文件描述符加1,這個例子中numfds的值應為sockfd+1;當select返回時,readfds將被修改,指示某個文件描述符已經(jīng)準備被讀取,你可以通過FD_ISSSET()來測試。為了實現(xiàn)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參數(shù)是一個指向struct timeval類型的指針,它可以使select()在等待timeout長時間后沒有文件描述符準備好即返回。struct timeval數(shù)據(jù)結構為:
      struct timeval {
       int tv_sec; /* seconds */
       int tv_usec; /* microseconds */ };

      POP3客戶端實例

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

    #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)編輯 收藏

    僅列出標題  下一頁
    主站蜘蛛池模板: 成熟女人特级毛片www免费| 四虎国产精品永久免费网址| 亚洲日本va在线观看| 亚洲人成7777影视在线观看| 亚洲精品无码高潮喷水A片软| 国产亚洲精品2021自在线| 污网站在线观看免费| a级午夜毛片免费一区二区| 男女免费观看在线爽爽爽视频| 日韩a级毛片免费视频| 亚洲乱码精品久久久久..| 亚洲乱码卡三乱码新区| 可以免费看的卡一卡二| 亚洲av乱码一区二区三区| 国产精品无码永久免费888| 全免费毛片在线播放| 香蕉大伊亚洲人在线观看| 麻豆精品成人免费国产片| 国产精品免费视频网站| 666精品国产精品亚洲| 老妇激情毛片免费| 免费人成视频在线| 亚洲色欲www综合网| 91网站免费观看| 国产国拍亚洲精品mv在线观看| 亚洲国产欧美一区二区三区| 免费观看久久精彩视频| 亚洲国产精品久久久久秋霞影院| fc2成年免费共享视频18| 亚洲日韩精品无码一区二区三区| 亚洲av永久中文无码精品| 亚洲色欲久久久久综合网| 亚洲欧美第一成人网站7777| 亚洲第一区精品观看| 亚洲人成色777777精品| 亚洲男人在线无码视频| 和老外3p爽粗大免费视频 | 国产精品白浆在线观看免费| 国产成人99久久亚洲综合精品| 国产99视频精品免费专区| 亚洲高清视频在线|