二級輔導(dǎo):由C++轉(zhuǎn)向C#需要注意的變化(四)

字號:

在網(wǎng)絡(luò)上讀取文件
    在C++中,在網(wǎng)絡(luò)上讀取文件需要有相當(dāng)?shù)木幊碳记桑?NET對此提供了廣泛的支持。事實(shí)上,在網(wǎng)絡(luò)上讀取文件僅僅是基礎(chǔ)類庫中Stream類的另一種應(yīng)用。
    首先,為了對TCP/IP端口(在本例中是65000)進(jìn)行監(jiān)聽,我們需要創(chuàng)建一個TCPListener類的實(shí)例。
    TCPListenertcpListener=newTCPListener(65000);
    一旦創(chuàng)建后,就讓它開始進(jìn)行監(jiān)聽。
    tcpListener.Start();
    現(xiàn)在就要等待客戶連接的要求了。
    SocketsocketForClient=tcpListener.Accept();
    TCPListener對象的Accept方法返回一個Socket對象,Accept是一個同步的方法,除非接收到一個連接請求它才會返回。如果連接成功,就可以開始向客戶發(fā)送文件了。
    if(socketForClient.Connected)
    {
    ???
       接下來,我們需要創(chuàng)建一個NetworkStream類,將報(bào)路傳遞給constructor:
    NetworkStreamnetworkStream=newNetworkStream(socketForClient);
    然后創(chuàng)建一個StreamWriter對象,只是這次不是在文件上而是在剛才創(chuàng)建的NetworkStream類上創(chuàng)建該對象:
    System.IO.StreamWriterstreamWriter=
    newSystem.IO.StreamWriter(networkStream);
    當(dāng)向該流寫內(nèi)容時(shí),流就通過網(wǎng)絡(luò)被傳輸給客戶端。
    客戶端的創(chuàng)建
    客戶端軟件就是一個TCPClient類的具體例子,TCPClient類代表連向主機(jī)的一個TCP/IP連接。
    TCPClientsocketForServer;
    socketForServer=newTCPClient("localHost",65000);
    有了TCPClient對象后,我們就可以創(chuàng)建NetworkStream對象了,然后在其上創(chuàng)建StreamReader類:
    NetworkStreamnetworkStream=socketForServer.GetStream();
    System.IO.StreamReaderstreamReader=
    newSystem.IO.StreamReader(networkStream);
    現(xiàn)在,只要其中有數(shù)據(jù)就讀取該流,并將結(jié)果輸出到控制臺上。
    do
    {
    outputString=streamReader.ReadLine();
    if(outputString!=null)
    {
    Console.WriteLine(outputString);
    }
    }
    while(outputString!=null);
    為了對這一段代碼進(jìn)行測試,可以創(chuàng)建如下一個測試用的文件:
    Thisislineone
    Thisislinetwo
    Thisislinethree
    Thisislinefour
    這是來自服務(wù)器的輸出:
    Output(Server)
    Clientconnected
    SendingThisislineone
    SendingThisislinetwo
    SendingThisislinethree
    SendingThisislinefour
    Disconnectingfromclient...
    Exiting...下面是來自客戶端的輸出:
    Thisislineone
    Thisislinetwo
    Thisislinethree
    Thisislinefour
    屬性和元數(shù)據(jù)
    C#和C++之間一個顯著的區(qū)別是它提供了對元數(shù)據(jù)的支持:有關(guān)類、對象、方法等其他實(shí)體的數(shù)據(jù)。屬性可以分為二類:一類以CLR的一部分的形式出現(xiàn),另一種是我們自己創(chuàng)建的屬性,CLR屬性用來支持串行化、排列和COM協(xié)同性等。一些屬性是針對一個組合體的,有些屬性則是針對類或界面,它們也被稱作是屬性目標(biāo)。
    將屬性放在屬性目標(biāo)前的方括號內(nèi),屬性就可以作用于它們的屬性目標(biāo)。
    [assembly:AssemblyDelaySign(false)]
    [assembly:AssemblyKeyFile(".\\keyFile.snk")]
    或用逗號將各個屬性分開:
    [assembly:AssemblyDelaySign(false),
    assembly:AssemblyKeyFile(".\\keyFile.snk")]
    自定義的屬性
    我們可以任意創(chuàng)建自定義屬性,并在認(rèn)為合適的時(shí)候使用它們。假設(shè)我們需要跟蹤bug的修復(fù)情況,就需要建立一個包含bug的數(shù)據(jù)庫,但需要將bug報(bào)告與專門的修正情況綁定在一塊兒,則可能在代碼中添加如下所示的注釋:
    //Bug323fixedbyJesseLiberty1/1/2005.
    這樣,在源代碼中就可以一目了然地了解bug的修正情況,但如果如果把相關(guān)的資料保存在數(shù)據(jù)庫中可能會更好,這樣就更方便我們的查詢工作了。如果所有的bug報(bào)告都使用相同的語法那就更好了,但這時(shí)我們就需要一個定制的屬性了。我們可能使用下面的內(nèi)容代替代碼中的注釋:
    [BugFix(323,"JesseLiberty","1/1/2005")Comment="Offbyoneerror"]
    與C#中的其他元素一樣,屬性也是類。定制化的屬性類需要繼承System.Attribute:
    publicclassBugFixAttribute:System.Attribute
    我們需要讓編譯器知道這個屬性可以跟什么類型的元素,我們可以通過如下的方式來指定該類型的元素:
    [AttributeUsage(AttributeTargets.ClassMembers,AllowMultiple=true)]
    AttributeUsage是一個作用于屬性的屬性━━元屬性,它提供的是元數(shù)據(jù)的元數(shù)據(jù),也即有關(guān)元數(shù)據(jù)的數(shù)據(jù)。在這種情況下,我們需要傳遞二個參數(shù),第一個是目標(biāo)(在本例中是類成員。),第二個是表示一個給定的元素是否可以接受多于一個屬性的標(biāo)記。AllowMultiple的值被設(shè)置為true,意味著類成員可以有多于一個BugFixAttribute屬性。如果要聯(lián)合二個屬性目標(biāo),可以使用OR操作符連接它們。
    [AttributeUsage(AttributeTargets.Class|AttributeTargets.Interface,AllowMultiple=true)]
    上面的代碼將使一個屬性隸屬于一個類或一個界面。
    新的自定義屬性被命名為BugFixAttribute。命名的規(guī)則是在屬性名之后添加Attribute。在將屬性指派給一個元素后,編譯器允許我們使用精簡的屬性名調(diào)用這一屬性。因此,下面的代碼是合法的:
    [BugFix(123,"JesseLiberty","01/01/05",Comment="Offbyone")]
    編譯器將首先查找名字為BugFix的屬性,如果沒有發(fā)現(xiàn),則查找BugFixAttribute。
    每個屬性必須至少有一個構(gòu)造器。屬性可以接受二種類型的參數(shù):環(huán)境參數(shù)和命名參數(shù)。在前面的例子中,bugID、編程人員的名字和日期是環(huán)境參數(shù),注釋是命名參數(shù)。環(huán)境參數(shù)被傳遞到構(gòu)造器中的,而且必須按在構(gòu)造器中定義的順序傳遞。
    publicBugFixAttribute(intbugID,stringprogrammer,stringdate)
    {
    this.bugID=bugID;
    this.programmer=programmer;
    this.date=date;
    }
    Namedparametersareimplementedasproperties.