国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

Visual C#建立簡單消息傳遞系統(1)

2024-07-21 02:20:26
字體:
來源:轉載
供稿:網友
 摘要:本文討論基于套接字(socket)的體系結構以及怎樣建立一個高效的、易于使用的、可以同時在pc和pocket pc上運行的消息傳遞(message-passing)系統。

  套接字和消息

  目前,大多數web服務和所有的遠程應用程序都使用了遠程過程調用(remote-procedure-call,rpc)方法。你所做工作好像是在調用一個函數,但是在其后臺執行了大量的操作以確保它在服務器上發生。在較低的層次,系統是在兩臺計算機之間傳遞消息,但這是不可視的。

  然而,當你轉換到套接字操作的時候,你就在純粹的基于消息的系統中編程了。這會改變你編寫的代碼的類型,因為讀取返回的數據的唯一途徑是通過消息。它與使用無返回值或輸出參數的.net類有點類似,在這些情況下所有的返回信息都需要通過事件傳遞。

  由于我希望服務器程序告訴客戶端什么時候應該改變曲目,使用消息就很有利,因為信息可以從服務器到達客戶端,不需要客戶端明確地請求該信息。但是,它要求你使用不同的方式達到目標。

  在解釋所有操作之前,我想先談論一點點安全性方面的問題。如果你在自己的計算機上打開了某個端口,其它人可能利用這個端口做不利的事情。他們可能希望寫入沒有意義的信號,以確定自己是否能夠控制你的計算機或者使它崩潰。當你編寫這類應用程序的時候考慮一下這種可能性是必要的。我的例子將運行在防火墻后面的網絡上,所以我感覺到相對安全。

  簡單的套接字

  我從建立一個服務器程序開始,它能給一個整數加上1,下面是服務器端代碼:

public static void main()
{
ipaddress localaddr = ipaddress.parse("127.0.0.1");
tcplistener listener = new tcplistener(localaddr, 9999);

console.writeline("waiting for initial connection");
listener.start();
socket socket = listener.acceptsocket();
console.writeline("connected");
networkstream stream = new networkstream(socket);
binaryreader reader = new binaryreader(stream);
binarywriter writer = new binarywriter(stream);

int i = reader.readint32();
i++;
writer.write(i);
}

  它首先在本機的9999端口上建立了一個tcp監聽器,接著啟動監聽器并等待連接。一旦得到了連接,它就接收一個整數,給它加1,并把它發送回去。

  需要指出的是我在此處使用的本地地址是127.0.0.1。在測試的時候這種情形可以很好地運行,這個時候客戶端和服務器程序在相同的計算機上運行,但是當它們在不同的計算機上運行時,程序就不能運行了。在后面的部分中我將給出更復雜的代碼。

 傳遞消息

  通過套接字傳遞未經處理的數據毫無樂趣,而通過套接字傳遞對象可能更有趣一些。為了達到這個目標,我們需要一個得到對象并把它轉換為字節流的途徑。最明顯的解決方案是使用運行時(runtime)提供的串行化(serialization)支持。不幸的是,使用這種方法會有少量的問題。

  第一個問題是串行化需要很大的開銷,這意味著它使用的字節比傳遞數據必要的字節多一些。如果使用soap格式化,這個問題就更嚴重。這是否成為一個問題依賴于應用程序的性能需求。第二個問題是串行化在簡潔框架組件中不能使用。由于沒有簡單的實現方法,我們需要自己做這個工作。在這個過程中,我們做的事情比串行化要少多了。

  我們從建立一個枚舉開始,它定義了可以傳遞什么類型的消息:

public enum messagetype
{
requestemployee = 1,
employee,
}

  對于每種消息類型,我們需要一個對象定義該對象:

public class requestemployee: isocketobject
{
int id;
public requestemployee(int id)
{
this.id = id;
}

}

public requestemployee(binaryreader reader)
{
id = reader.readint32();
}

public int id
{
get
{
return id;
}
}

public void send(binarywriter writer)
{
writer.write((int) messagetype.requestemployee);
writer.write(id);
}
}

  我們使用的這種途徑與iserializable接口很相似。isocketobject接口定義了一個send()函數,它串行化通過通道的數據,接著還有一個并行化該數據的構造函數。

  在這些對象中的某個串行化自身的時候,它發送的第一個信息是消息標識符。它讓接收者知道將到達哪種類型的對象并建立該對象。下面是客戶端的代碼:

requestemployee requestemployee = new requestemployee(15);
requestemployee.send(writer);

messagetype messagetype = (messagetype) reader.readint32();

switch (messagetype)
{
case messagetype.employee:
employee employee = new employee(reader);
console.writeline("{0} = {1}", employee.name, employee.address);
break;
}

  requestemployee這段代碼建立了一個對象并把它發送給服務器程序,接著它找出返回的是哪種對象,并且并行化它。

  盡管這個示例項目被標記為client和server,但是兩者之間唯一真正的差別是連接建立的方式。當這個過程完成后,它們都使用相似的代碼發送和接收消息,即使它們需要處理自己的消息集合。
  • 本文來源于網頁設計愛好者web開發社區http://www.html.org.cn收集整理,歡迎訪問。
  • 發表評論 共有條評論
    用戶名: 密碼:
    驗證碼: 匿名發表
    主站蜘蛛池模板: 云阳县| 扎囊县| 隆昌县| 泗洪县| 陈巴尔虎旗| 临江市| 谢通门县| 盱眙县| 化州市| 永顺县| 灌阳县| 汨罗市| 尚志市| 共和县| 玉门市| 沂南县| 轮台县| 长丰县| 同德县| 五寨县| 长垣县| 石泉县| 桐乡市| 汉寿县| 蓝山县| 拉孜县| 黔西| 二连浩特市| 娱乐| 平谷区| 阿鲁科尔沁旗| 文安县| 镶黄旗| 建平县| 喀喇| 宣汉县| 大关县| 兴宁市| 都兰县| 洪泽县| 孟津县|