人人做人人澡人人爽欧美,国产主播一区二区,久久久精品五月天,羞羞视频在线观看免费

當前位置:蘿卜系統(tǒng)下載站 > 技術(shù)開發(fā)教程 > 詳細頁面

Visual C#創(chuàng)建容易消息傳遞系統(tǒng)(2)

Visual C#創(chuàng)建容易消息傳遞系統(tǒng)(2)

更新時間:2022-06-07 文章作者:未知 信息來源:網(wǎng)絡(luò) 閱讀次數(shù):

面向?qū)ο笤O(shè)計vs.實用主義

  這種方法的缺點之一是你必須使用一個大的switch語句結(jié)束,但是前輩一直教導(dǎo)我們大的switch語句是較差的設(shè)計的表現(xiàn)。通常的面向?qū)ο螅∣bject Oriented,OO)的途徑是使用多態(tài)性(polymorphism)的。為了達到這個目的,我們先建立一個抽象的基類(base class),接著從該類衍生出所有的消息對象。每個類需要執(zhí)行串行化、并行化和處理消息等多個方法,主要的代碼是:

  · 讀取消息類型

  · 建立實例(使用反射)

  · 調(diào)用虛HandleMessage()函數(shù)

  這樣做是可以實現(xiàn)的,但是效果很差,我并不喜歡。首先,編寫建立實例的代碼很難,并且由于它使用了反射,它的速度更慢。更重要的是,消息的處理過程并不在HandleMessage()函數(shù)之內(nèi),這意味著它必須是共享庫的一部分。這是不宜使用的,因為消息的處理過程與消息如何傳遞沒有什么關(guān)系。由于這些問題的存在,我依然決定使用較少面向?qū)ο蟮歉尤菀拙帉懙耐緩健?br>
  前面的示例只處理了單個消息。在現(xiàn)實世界中,我們需要同時處理多個消息。

  服務(wù)器端的多線程

  我的最終的目標是把該服務(wù)器程序的功能添加到一個已有的應(yīng)用程序中。因為不希望修改已有的應(yīng)用程序的代碼,我就必須在某個線程上運行服務(wù)器程序。同樣,我希望可以同時接受多個連接。

  上面的例子在端口9999上監(jiān)聽,但是由于一個客戶端只能與一個端口對話,我需要為每個連接使用不同端口的途徑。SocketListener類將在9999端口上監(jiān)視,當新的連接請求到達的時候,它將查找一個未使用的端口并把它發(fā)送回給客戶端。下面是這個類的大致情形:

public class SocketListener
{
int port;
Thread thread;

public SocketListener(int port)
{
this.port = port;
ThreadStart ts = new ThreadStart(WaitForConnection);
thread = new Thread(ts);
thread.IsBackground = true;
thread.Start();
}

public void WaitForConnection()
{
// 主要的代碼
}
}


  WaitForConnection()是執(zhí)行所有這些操作的方法。這個類的構(gòu)造函數(shù)執(zhí)行建立新線程的任務(wù),這個線程將運行WaitForConnection()。打開套接字并接受連接與前面的例子相似。下面是該線程的主循環(huán):

while (true)
{
Console.WriteLine("Waiting for initial connection");
listener.Start();
Socket socket = listener.AcceptSocket();
NetworkStream stream = new NetworkStream(socket);
BinaryReader reader = new BinaryReader(stream);
BinaryWriter writer = new BinaryWriter(stream);

Console.WriteLine("Connection Requested");

int userPort = port + 1;
TcpListener specificListener;
while (true)
{
try
{
specificListener =
new TcpListener(localAddr, userPort);
specificListener.Start();
break;
}
catch (SocketException)
{
userPort++;
}
}
//遠程用戶應(yīng)該使用specificListener。
//把該端口發(fā)送回給遠程用戶,并為我們在該端口上建立服務(wù)器應(yīng)用程序。
SocketServer socketServer = new SocketServer(specificListener);

writer.Write(userPort);
writer.Close();
reader.Close();
stream.Close();
socket.Close();
}

  我希望能夠支持多個連接,因此使用一個端口以便于客戶端表明它們希望建立一個連接,接著服務(wù)器程序找到一個空的端口并把該端口發(fā)送回給客戶端,該端口用于特定客戶端的連接。

  我沒有找到查找未使用端口的方法,因此該While循環(huán)用于找出未使用的端口。接著它把該端口號發(fā)送回客戶端并清除對象。

  此處還有需要指出的一點點微妙之處。SocketServer的原始版本把端口號作為一個參數(shù)。不幸的是,這意味著在該端口上建立監(jiān)聽器之前客戶端不能作出請求,這是很不好的。為了防止出現(xiàn)這種情況,我在給客戶端發(fā)送端口號之前建立了TcpListener,它確保不會出現(xiàn)這種緊急情況。

  SocketServer類建立了額外的線程,并使用了下面的主循環(huán):

try
{
while (true)
{
MessageType messageType = (MessageType) reader.ReadInt32();

switch (messageType)
{
case MessageType.RequestEmployee:
Employee employee =
new Employee("Eric Gunnerson", "One Microsoft Way");
employee.Send(writer);
break;
}
}
}
catch (IOException)
{

}
finally
{
socket.Close();
}

  這個主循環(huán)是一個簡單的獲取請求/處理請求的循環(huán)。try-catch-finally在此處用于當客戶端斷開連接的時候從異常中恢復(fù)過來。

 客戶端的事件

  在客戶端,我編寫了一個Windows傳統(tǒng)客戶端程序,可以供PC使用也可以供Pocket PC使用。該Windows窗體環(huán)境是基于事件的,而且使用事件處理套接字消息也是理想的。這是通過SocketClient類實現(xiàn)的。第一步是為每個消息定義一個委托和事件:

public delegate void EmployeeHandler(Employee employee);
public event EmployeeHandler EmployeeReceived;

  第二步是編寫發(fā)送事件的代碼:

case MessageType.Employee:
Employee employee = new Employee(reader);
if (EmployeeReceived != null)
form.Invoke(EmployeeReceived, new object[] {employee});
break;

  當事件發(fā)生的時候就應(yīng)該更新窗體了。為了更可靠,這個操作需要在主UI線程上發(fā)生。這是通過調(diào)用窗體的Invoke()實現(xiàn)的,它將安排在主UI線程上調(diào)用的委托。

  因為這種基于消息的體系結(jié)構(gòu),服務(wù)器程序要有對于異步事件的內(nèi)建的支持。示例有一個CurrentCount消息,它是由服務(wù)器程序每秒鐘發(fā)送的。

  總結(jié)

  我對這個基于套接字的體系結(jié)構(gòu)很滿意,它是輕量級的、易于使用的,并且它可以同時在PC和Pocket P

溫馨提示:喜歡本站的話,請收藏一下本站!

本類教程下載

系統(tǒng)下載排行

網(wǎng)站地圖xml | 網(wǎng)站地圖html
主站蜘蛛池模板: 土默特右旗| 新余市| 金乡县| 德江县| 邯郸市| 孝昌县| 新沂市| 双辽市| 博白县| 江油市| 腾冲县| 冕宁县| 社会| 清远市| 广饶县| 桐庐县| 略阳县| 香格里拉县| 柘城县| 鄂伦春自治旗| 中阳县| 永兴县| 阿巴嘎旗| 连城县| 科尔| 祁阳县| 茂名市| 宁夏| 资阳市| 普陀区| 即墨市| 株洲市| 大理市| 元氏县| 吉林市| 宁强县| 龙口市| 库尔勒市| 徐水县| 温宿县| 伽师县|