咱們先把前面的代碼封裝成一個完整的類,由於跟網絡相關的方法並不必定是創建socket的服務器和客戶端,因此仍是應該把兩個分開,好比獲取本機IP,修改本機IP,PING遠程主機這些事情應該放在一個單獨的類裏面,並且裏面的方法應該是靜態的(一個應用不會須要多個實例來作上面講的這些事情),因此我我的建議作成一個單獨的類FunctionNetwork,這樣可讓主程序很簡潔 數組
注意可能涉及到IP地址自動獲取和手動修改的方法,須要額外的DLL引用(System.Management),這部分功能暫時用不上 服務器
封裝客戶端的Socket類方法比較簡單,大部分只要照抄前面的代碼便可。可是在接收數據的時候咱們使用了委託的方法對外傳遞數據。通常事件和委託成對使用比較方便(先不要管爲何這麼寫,照着抄就好了),delegate部分聲明委託的名稱和要傳遞數據的類型,event部分聲明事件的名稱。這個socket客戶端的事件也就三種(鏈接成功,收到數據,斷開鏈接,固然你也能夠定義額外的事件,好比發送成功也算事件,發送失敗也算事件) 網絡
當socket客戶端已經OnRecieveMessageFromServerSuccess(收到的消息)發出去的時候,那麼問題來了,誰來處理這個數據?咱們當前的程序是須要主程序去處理,因此主程序在初始化的時候,只要聲明當TheClient發生XXX事件的時候,就把他要傳遞的變量經過 +=的函數執行一次(注意用Tab自動補全,)而後就能夠拿着這個類要傳遞的數據顯示到控件上了。能夠想象,若是不是Form1要用,而是其餘的類或者窗體要用,也只要初始化的時候添加一條委託事件的綁定函數就能夠了,確實很是方便(否則你怎麼把某個類的某個方法產生的數據往外發?委託和事件就是爲了解決這個問題來的) socket
尚未完,咱們前面介紹的直接更新界面的數據,是經過關閉跨線程訪問控件檢測實現的,實際上這樣作還不規範,實際上當主程序收到消息要更新控件以前,先判斷XXX控件是否InvokeRequired,而後若是沒有要執行Invoke方法,它裏面的寫法比較難看懂,也不須要理解,只要能照着葫蘆畫瓢就好了 函數
與之對應的,另外兩個委託的方法也是這樣作(即使有多個控件要更新,也只須要考慮一個控件.InvokeRequired便可) 測試
爲了更清晰的看到從Server端發過來的數據,能夠用字符串遍歷出來(例如服務器發送一個字符A,其實除了這個字符還包括了回車換行 \r\n),能夠看到咱們定義的byte數組只有前面三位是有意義的(分別是65/13/10),查ASCII碼錶能夠發現就是A+回車+換行(因此若是要解決中文亂碼的問題,也須要響應的寫轉成byte和從byte提取,可能一個byte不足以表示一箇中文,而大部分軟件只認爲傳過來一個一個byte就是一個字符,因此強硬的把兩個或者更多byte湊在一塊兒纔有意義的中文拆了致使的亂碼) ui
當服務器斷開鏈接的時候,實際上仍是會發送一個空消息(固然你本身寫服務器的或者客戶端的時候也能夠發送自定義消息),仍是前面的方法能夠測試出來,無論在服務器端點了StopListening直接中止服務器,仍是Disconnect僅僅踢掉這個客戶端,客戶端都還能最後收到一筆byte數組,而這個數組裏面啥也沒有,這條消息就能夠用來判斷是否是服務器主動斷開了鏈接 spa
因此咱們能夠把軟件作的比較完善,若是是服務器點擊的斷開鏈接,則提示服務器主動斷開,若是是客戶端點擊的端口,則提示客戶端要斷開 線程
並且不論是主動仍是被動的斷開鏈接,界面的按鈕都要重置爲鏈接可用,斷開不可用,發送不可用(若是鏈接成功則相反),因此這也是用委託和事件的方式封裝整個類的可能行爲及觸發的其餘方法優點所在,若是不用事件和委託,這些事情也能作,可是要花費的代碼和維護,修改的成本會大得多。 3d
更多教學視頻和資料下載,歡迎關注如下信息:
個人優酷空間:
http://i.youku.com/acetaohai123
個人在線論壇:
http://csrobot.gz01.bdysite.com/
問題交流:
QQ:910358960