實現基於事件通知的.Net通訊端

來源:互聯網
上載者:User

以前學過MFC,我用過的它裡面的封裝Winsock的兩個類CSocket和CAsyncSocket,我一直覺得它哪個事件通知的功能比較不錯,特別是在串連的兩方收發資料沒有一定的規律的時候比較有用,雖然不用它的事件通知也可以實現功能,但是你需要迴圈檢測通訊端的狀態或者阻塞等待,如果每次都要做這些瑣碎的工作豈不是很麻煩,於是我就想對這些功能作一次封裝。當然在.net裡面採用delegate和event是最好的選擇了。下面就是我實現的一些細節:

先講一下思路:其實這個還是很簡單了,估計高手們會不屑一顧了^_^。當通訊端開始工作,比如開始監聽、開始串連的時候,啟動一個線程不停的檢測通訊端的狀態,當某一事件的狀態條件滿足時就觸發此事件,要知道具體檢測通訊端狀態的方法,請往下看。

平常用通訊端編成的時候可能需要用到的功能就是:串連成功或者失敗的通知、在監聽的通訊端上有掛起的串連的通知、有資料可以接受的通知、通訊端關閉的通知、還有通訊端空閑可以發送資料的通知等,我也就使對上面幾個功能作了封裝,不過我覺得最後面一個功能用處不大???

我的Socket類是從System.Net.Sockets.Socket繼承下來的,類名TcpEventSocket,實現如下:

先申明事件的委託類型,具體看代碼

public delegate void AcceptConnectionHandler();

public delegate void ConnectCompletedHandler(bool connected); //connected表明串連成功與否

public delegate void DataCanSendHandler();

public delegate void DataCanReceiveHandler(int buffersize); //當前可以接受的資料量

public delegate void SocketClosedHandler();

這些類型具體什麼意思應該能看出來吧,另外還要申明對應的事件

public event AcceptConnectionHandler AcceptConnection;

public event ConnectCompletedHandler ConnectCompleted;

public event DataCanSendHandler DataCanSend;

public event DataCanReceiveHandler DataCanReceive;

public event SocketClosedHandler SocketClosed;

另外加了幾個虛方法,這幾個方法用來觸發事件

protected virtual void OnAcceptConnection();
protected virtual void OnConnectCompleted(bool connected)

protected virtual void OnDataCanSend()
protected virtual void OnDataCanReceive(int buffersize)

protected virtual void OnSocketClosed()

為了在適當的事機啟動檢測線程,我重寫了幾個基類的方法:

new public void Listen(int backlog)

{

base.Listen(backlog);

sockState = SocketState.Listenning;

if (!checkThread.IsAlive)

checkThread.Start();

}

new public void Connect(EndPoint remoteEP)

{

try

{

base.Connect(remoteEP);

this.Blocking = false; //設定非阻塞狀態,以便事件通知的效率

if (!checkThread.IsAlive)

checkThread.Start();

}

catch(SocketException)

{

OnConnectCompleted(false);

}

}

這兩個方法實際編成中都應該首先被調用的,所以有他們啟動檢測線程比較合適,另外線程啟動了必然也要中止,於是我重寫了Close方法

new public void Close()

{

if(checkThread.IsAlive) //先中止線程再關閉串連

checkThread.Abort();

base.Close();

sockState = SocketState.Disconnected;

OnSocketClosed();

}

於是剩下的工作就是怎麼檢測通訊端了,Socket類有個Select的靜態方法,它可以檢測很多通訊端的狀態,不過這裡只需要檢測一個,所以直接用Socket的Poll方法,Poll的具體用法可以看MSDN,我這裡用代碼說明我對通訊端的檢測方法

while(true) //迴圈檢查

{

if (sockState == SocketState.Disconnected) //如果當前沒有串連

{

if (Poll(500, SelectMode.SelectWrite))

OnConnectCompleted(true); //如果為可寫狀態,則表示串連成功

}

else if(sockState == SocketState.Listenning)

{

if (Poll(500, SelectMode.SelectRead)) //如果在監聽狀態發現通訊端有資料可讀則表示已經有人串連上來可以調用Accept接受串連

OnAcceptConnection();

}

else //這裡sockState = SocketState.Connected

{

if (Poll(500, SelectMode.SelectWrite)) //如果有可寫狀態則表示可以發送資料

OnDataCanSend();

if (Poll(500, SelectMode.SelectRead)) //如果有可讀狀態

{

if (Available > 0) //如果有資料可讀表示可以調用Receive接受資料

OnDataCanReceive(Available);

else

{

OnSocketClosed(); //沒資料可讀表示串連已經關閉

break;

}

}

}

//如果沒有串連並且有錯誤狀態,則串連失敗

if (sockState == SocketState.Disconnected && Poll(500, SelectMode.SelectError))

OnConnectCompleted(false);

}

這裡的OnXXX方法就是執行事件通知的方法,並且衍生類別中可以重載這些方法直接獲得事件通知而不需要掛界別的事件通知處理函數(類似於MFC的OnAccept等虛函數)。不過派生的函數集的調用基類的相應方法哦。很可惜沒有重寫Socket.Accept方法,讓它返回一個TcpEventSocket,這樣應該就比較完整了,只可惜我不知道怎麼做^_^,如果誰知道的話歡迎指教。

事件通知機制已經基本完成,所缺乏的只是大量的測試(我做了幾下最簡單的測試,慚愧!!^_^)

如果有問題請聯絡 yzx110@bit.edu.cn

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.