乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      與Socket的第一次“約會”

       orion360doc 2010-12-29
      .NET 4.0網(wǎng)絡開發(fā)入門之旅--

      與Socket的第一次“約會” 

      注: 

          這是一個針對 網(wǎng)絡開發(fā)領域初學者 的系列文章,可作為《.NET 4.0 面向對象編程漫談 》一書的擴充閱讀,寫作過程中我假設讀者可以對照閱讀此書的相關章節(jié),不再浪費筆墨重復介紹相關的內(nèi)容。 

          對于其他類型的讀者,除非您已經(jīng)有相應的.NET 技術背景與一定的開發(fā)經(jīng)驗,否則,閱讀中可能會遇到困難。 

          我希望這系列文章能讓讀者領略到網(wǎng)絡開發(fā)的魅力! 

          另外,這些文章均為本人原創(chuàng),請讀者尊重作者的勞動,我允許大家出于知識共享的目的自由轉載這些文章及相關示例,但未經(jīng)本人許可,請不要用于商業(yè)盈利目的。 

            本文如有錯誤,敬請回貼指正。 

          謝謝大家! 

       

                                                                金旭亮 

      =================================================

      點擊以下鏈接閱讀本系列前面的文章: 

       

      《 開篇語—— 無網(wǎng)不勝》 
      《 IP知多少》 

      《我在“網(wǎng)” 中央 》 

      =================================================

            在前面的文章中,我們已經(jīng)介紹了使用.NET平臺開發(fā)網(wǎng)絡應用程序諸如IP地址、網(wǎng)絡接口之類的背景知識,本文將介紹.NET網(wǎng)絡應用程序的主角--Socket。如果把Socket比喻為一位“美女”,那么有關她的“愛情故事”實在太多,而本系列后繼的文章,就圍繞著這位“美女”所展開。 
      1    Socket美女的“家庭背景” 
          Socket,中文譯為“套接字”,最早在UNIX中引入并得到廣泛應用,后來微軟在設計Windows時引入了UNIX中的這個概念和相應的設計理念,并針對Windows的特性略作調(diào)整,形成了Windows平臺上的Socket,簡稱為“WinSock”,并為開發(fā)者提供了一整套的API,稱為“Windows WinSock Win32 API ”。 
            WinSock經(jīng)歷了兩個版本,Windows Sockets 2是目前用得最多的版本(參看 http://en./wiki/Winsock ),微軟似乎從來沒有宣布要開發(fā)WinSock 3,也許“永遠也不會有”了。
           圖 1所示為.NET平臺下網(wǎng)絡應用程序的層次架構: 


       


      圖 1


          WinSock在底層使用一個運行于操作系統(tǒng)核心的系統(tǒng)驅動(Windows Sockets Knernel-mode Driver)tcpip.SYS,由它們負責管理網(wǎng)絡連接和緩沖管理。 
          還有另一個驅動Afd.sys(Ancillary Function Driver for WinSock)則用于支持基于 window socket的應用程序,比如ftp、telnet等,被稱為“ Windows NT 套接字驅動程序 ”。
          早期的Windows開發(fā)者,需要使用C/C++去調(diào)用WinSock,比如MFC就提供了一個“CSocket”類封裝底層的Socket。 
          .NET也提供了一組類來封裝WinSock Win32 API,這些類集中于System.Net這一命名空間中,其中的核心類型就是Socket。
          Socket類是對WinSock API一個很淺的封裝,擁有不少方法直接對應于WinSock中的C/C++函數(shù),比如Poll、Select、IOControl等。
          Socket有一個Handle屬性,它引用位于操作系統(tǒng)核心的Socket核心對象。 

          提示: 
          有關系統(tǒng)核心對象(Kernel Object)的通俗解釋,請參看《.NET 4.0面向對象編程漫談 》中的15.1.2節(jié)《操作系統(tǒng)的進程管理》 

          Socket提供了眾多的屬性,還提供了SetSocketOption方法來設置各種選項,對.NET網(wǎng)絡應用程序的數(shù)據(jù)通訊進行“微調(diào)”。
          Socket的功能出奇地強大,在.NET平臺上,它支持以下四種典型的編程模式: 

      (1) 居于阻塞模式的Socket編程(單線程或多線程的),每個線程處理一個客戶端連接 
      (2)“非阻塞”模式的Socket編程,這是早期UNIX為提升網(wǎng)絡應用程序性能而采用的編程模式,出于兼容和方便移植原有程序的目的而保留,建議新開發(fā)的.NET網(wǎng)絡程序不要再使用。
      (3) 使用IAsyncResult的異步編程模式:Socket類提供有一堆的“BeginXXX/EndXXX”方法實現(xiàn)異步Socket編程,使用線程池中的線程完成工作,性能較好。
      (4)    使用EAP的異步編程模式:Socket類提供了“另一堆”以“Async”結尾的方法,在底層使用Windows操作系統(tǒng)的Completion Port(完成端口)和Overlapped I/O mechanism(重疊輸入/輸出機制),據(jù)說可以提供“最高”的性能。
          在后面的文章中,將逐步地展開介紹這些編程模式。

          提示: 
          強烈建議讀者仔細閱讀《.NET 4.0面向對象編程漫談 》中的第10章《異步編程模式》,以提前掌握.NET異步編程的基礎知識與基本技能,否則,后面的文章可以不用看了。 

          了解了Socket這位“美女”的“家庭背景”之后,在與她進行第一次“約會”之前,我們不妨弄清楚一個問題:
          現(xiàn)在我們還有必要掌握Sokcet編程技術嗎? 

      2    Socket是否已人老珠黃? 
          基于Socket開發(fā)網(wǎng)絡應用程序已經(jīng)有很多年的歷史了,現(xiàn)在的新技術層出不窮,在.NET平臺之上,WCF大有“一統(tǒng)江湖”的勢頭,Socket是否真的“人老珠黃”?
          請看圖 2所示的多層“松花蛋”: 

       

      圖 2 

          圖 2說明,WCF與WinSocket等底層技術之間實際上是一種“包含”關系,每一層都在下一層所提供服務的基礎上,又擴充了新的功能,越外層的應用程序,可以使用的功能往往越多,開發(fā)效率往往也會更高。
          WCF在WinSocket的基礎之上擴充了大量的功能,使用它可以很高效地開發(fā)網(wǎng)絡應用程序,尤其非常適合于開發(fā)基于SOA的分布式軟件系統(tǒng),但這并不是說它可以完全把Socket打入冷宮。在不少場合,拋棄WCF那龐大的框架,直接使用Socket更合適:
          (1)需要實現(xiàn)自己的通訊協(xié)議的場合(比如你要架設一個網(wǎng)絡游戲服務器)
          (2)你開發(fā)的系統(tǒng)需要實現(xiàn)“一問一答”的“交互式”運行模式
          (3)你希望能全面控制你的網(wǎng)絡應用程序的“每個方面”,不想花時間去理解WCF那個復雜無比的內(nèi)部架構
          (4)你的網(wǎng)絡應用程序應用背景非常單一與明確,比如就解決一個問題:定期將分布于多臺計算機上的數(shù)據(jù)文件上傳“匯總”到一臺中心服務器上。
          (5)……
          如果需要基于各種標準協(xié)議(比如WS-*等)開發(fā)SOA的分布式軟件系統(tǒng),再使用Socket就不合適了,那會大大地增加開發(fā)的工作量和難度,WCF更適合于解決這個問題。
          在實際開發(fā)中,我們還可以混用WCF和Socket。比如我們可以基于WCF開發(fā)P2P的應用程序,使用NetPeerTcpBinding在P2P節(jié)點間“廣播消息”,然后,在兩個P2P節(jié)點之間直接使用Socket“私下”里傳送一個“秘密”文件。
          是可謂“運用之妙,存乎一心 ”。
          好了,下面就介紹使用Socket開發(fā)的最基礎知識吧。


      3     第一個Socket應用程序 
          一般我們都將網(wǎng)絡應用中用于提供“服務”的一方稱為“服務端應用程序(Server)”,另一方訪問這些服務的稱為“客戶端應用程序(Client)”。Server端和Client端的Socket用法是不一樣的。 
          3.1 服務端應用程序 
          開發(fā)網(wǎng)絡程序的第一步,是創(chuàng)建Socket對象,以下是示例代碼:

          Socket newsock = new Socket(
              AddressFamily.InterNetwork,    //使用IPv4
              SocketType.Stream, //使用可靠的雙向數(shù)據(jù)流,不保存信息邊界 
              ProtocolType.Tcp  //使用TCP協(xié)議 
          );

          緊接著,需要將Socket對象“綁定(Bind) ”到一個“終結點(IPEndPoint的實例)”。

          IPEndPoint ipep = new IPEndPoint(IP地址,打開端口);  //綁定 
          newsock.Bind(ipep); 

          提示: 
          前面的《IP知多少 》一文中介紹過IPEndPoint。WCF中也定義了“終結點 ”,它代表一個WCF服務的訪問點。 
          
          “綁定(Bind) ”這個術語非常值得關注,簡單地說,“綁定”就是將原先可能不相關的兩個事物“關聯(lián)”起來,打個可能不太恰當?shù)谋扔鳎?#8220;綁定”就是相愛的兩個人最終決定結婚,并領了結婚證。
          “綁定”的身影在.NET平臺中頻頻出現(xiàn),比如“數(shù)據(jù)綁定(DataBind)”,就是使用控件將數(shù)據(jù)源中的數(shù)據(jù)展示在應用程序的界面上,并且將用戶對數(shù)據(jù)的修改和查詢等傳給數(shù)據(jù)源。
          在Socket應用程序中,“綁定”的作用是讓某個Socket對象關聯(lián)上特定的網(wǎng)絡接口(Network Interface)。一臺網(wǎng)絡主機可能安裝有多個網(wǎng)絡接口,“綁定”之后,Socket對象將可以在指定那個網(wǎng)絡接口(Network Interface )上監(jiān)聽。如果不需要指定特定的網(wǎng)絡接口,也不在意使用的端口,那么,可以創(chuàng)建一個使用IPAddress.Any,端口為0的IPEndPoint,Socket綁定這一IPEndPoint之后,操作系統(tǒng)會決定最終使用哪個網(wǎng)絡接口,并且在“[1024,5000]”之間的選擇一個未用端口分配給此Socket。

      注意: 
          WCF中也有“綁定”,但WCF中的“綁定”的含義要豐富得多,它其實是一組特殊的對象,它的主要功能是創(chuàng)建用于實現(xiàn)WCF應用程序間相互通訊的“信道棧”,WCF基類庫中提供了一堆的“綁定”,特定的綁定使用特定的通訊協(xié)議和技術,比如NetTcpBinding采用TCP協(xié)議,NetMsmqBinding則使用了微軟消息隊列。 
          
          Socket對象綁定網(wǎng)絡接口之后,就可以監(jiān)聽并等待客戶端連接了: 

          newsock.Listen(10);  //開始監(jiān)聽
          Socket client = newsock.Accept(); //等待客戶端連接

          所謂“監(jiān)聽 (Listen) ”,其實是告訴操作系統(tǒng):“我關心本機某個網(wǎng)絡接口上的數(shù)據(jù)包,當有數(shù)據(jù)包到達,并且端口號和我所規(guī)定的一致,請通知我”。
          Socket.Listen方法的參數(shù)有著特殊的含義。此處暫時按下,留待后文分解。
          Socket.Accept方法等待客戶端發(fā)來的連接請求數(shù)據(jù)包,默認情況下,這一方法是“同步”方法,線程將在此處阻塞等待,直到有客戶發(fā)來連接請求。
          當客戶端發(fā)來連接請求時,Accept方法返回一個Socket對象,這個對象代表雙方已建立了一條數(shù)據(jù)通訊的鏈路,可以相互傳送數(shù)據(jù)了。這時,原先的Socket將得到“解放”,可以繼續(xù)監(jiān)聽。

          注意: 
          負責監(jiān)聽的Socket不負責發(fā)送與接收數(shù)據(jù),而Accept方法返回的Socket可以用于接收和發(fā)送數(shù)據(jù),但不能用于接收新的連接,同時,其RemoteEndPoint方法可以獲取遠程客戶端的IP地址和使用的端口 

          以下代碼調(diào)用剛得到的Socket對象的Receive方法接收客戶端發(fā)來的數(shù)據(jù):

          byte[] data = new byte[1024];
           int r ecv = client.Receive(data);

          Socket.Receive方法也是一個“阻塞”的同步方法,它將收到的數(shù)據(jù)保存到一個字節(jié)數(shù)組中,這個字節(jié)數(shù)組通常稱為“數(shù)據(jù)緩沖區(qū)”。

          提示: 
          數(shù)據(jù)緩沖區(qū)在Socket編程中非常重要,讀者會發(fā)現(xiàn),在開發(fā)中你時時刻刻都得關注它,一不小心,它就給你搗亂。 

          Receive方法的返回值代表接收的數(shù)據(jù)字節(jié)數(shù)。以下代碼使用這一返回值了解客戶端到底發(fā)來了什么消息: 

          Console.WriteLine(Encoding.UTF8 .GetString(data, 0, recv ));

          上面這句代碼中有幾點需要特別注意:
          (1)一定要使用recv來“定界”客戶端傳來的數(shù)據(jù)。
          (2)我們假設客戶端發(fā)送過來的消息是一個字符串,這里使用UTF8進行解碼。很明顯,這要求客戶端與服務端必須事先達成一致,使用同樣的編碼和解碼方式。這種需要在事先進行協(xié)商的“東西”,就是“通訊協(xié)議 ”。不同的網(wǎng)絡應用會使用不同的通訊協(xié)議,比如互聯(lián)網(wǎng)普遍使用HTTP,這是一個業(yè)界標準,而我們也可以定義自己的通訊協(xié)議,比如QQ就有自己的通訊協(xié)議。
          
          提示: 
          我在《 漫談.NET開發(fā)中的字符串編碼 》一文中介紹了字符串編碼的基礎知識。 

          數(shù)據(jù)接收完畢,服務端就可以斷開客戶的連接: 

          client.Shutdown(SocketShutdown.Both);  //通知OS,不再接收與發(fā)送數(shù)據(jù)
          client.Close();    //關閉Socket

          完成數(shù)據(jù)傳送任務之后,注意應該及時地關閉Socket。這通常分為兩步: 
          (1)調(diào)用Shutdown方法通知TCP/IP協(xié)議棧發(fā)送所有未發(fā)送的數(shù)據(jù),或停止接收數(shù)據(jù) 
          (2)調(diào)用Close方法關閉套接字。 
          Socket本身對應著一個核心對象,它有一個句柄(Handle)供操作系統(tǒng)內(nèi)核進行管理。因此,它不再有用時必須及時地被關閉,否則,有可能會造成嚴重的問題。

          提示: 
          操作系統(tǒng)能管理的句柄數(shù)是有限的,而網(wǎng)絡應用服務端程序通常會運行很長的時間,如果不及時地關閉不用的Socket,將導致它所占用的句柄不能及時回收,有可能導致服務器Down掉。 

          Socket本身實現(xiàn)了IDisposable接口,所以也可以使用using關鍵字實現(xiàn)“自動釋放”: 

          using (newsock)
          {
                 ……
          }  //自動關閉newsock 

          3.2 客戶端應用程序 
          客戶端應用程序與服務端大同小異:
          首先創(chuàng)建好一個Socket對象,然后再調(diào)用其Connect方法創(chuàng)建到服務端的連接,如果之前Socket沒有使用Bind方法指定一個端口,Connect方法會自動選擇一個未用的端口: 

          Socket server = new Socket( AddressFamily.InterNetwork,
                          SocketType.Stream,  ProtocolType.Tcp );
          server.Connect(服務端的IP終結點);

          如果Connect方法沒有拋出異常,則表示成功連接服務器,現(xiàn)在,就可以使用Socket對象的Send方法發(fā)送數(shù)據(jù),數(shù)據(jù)同樣保存于一個數(shù)據(jù)緩沖區(qū)(其實就是一個byte[])中: 

          server.Send(Encoding.UTF8 .GetBytes(要發(fā)送的消息));

          注意這里選擇的字符串編碼方式必須要與服務端一致,否則,將導致服務端無法正確地解碼出字符串。
          數(shù)據(jù)發(fā)送完畢,關閉套接字就行了。
          3.3 處理網(wǎng)絡應用程序中的異常 
          Socket對象的Connect、Send、Receive等方法都有可能出錯,這時,.NET基類庫將拋出一個SocketException,它實際上封裝的是底層WinSock出錯信息。
          每一個SocketException對象都有一個對應的錯誤號,其含義是由底層的WinSock定的。比如錯誤號為10048的SocketException其含義是:地址已被使用。發(fā)生這一異常的原因通常是你嘗試把兩個Socket對象綁定到同一個IPEndPoint。
          以下是Socket網(wǎng)絡應用程序中的典型代碼框架:

          Socket remote=new Socket(……);
          try
          {
              //……
              remote.Connect(iep);  //iep為遠程主機的終結點
              //……
              remote.Send(……);
              //……
          }
          catch (SocketException e)
          {
              Console.WriteLine("無法連接遠程主機 {0} ,原因:{1},
                  NativeErrorCode:{2},SocketErrorCode:{3}", iep.Address,
                  e.Message, e.NativeErrorCode, e.SocketErrorCode);
          }
          finally
          {
              server.Close();
          }

          示例項目IntroduceSocket展示了本文所介紹的知識(圖 3)。 

       

      圖 3



          到此,我們與“Socket美女”的“第一次約會”到此結束。您對她的第一印象如何? 

      點擊下載本文示例 


      ==============================================================================


          下一篇文章,將介紹Socket美女的“追求者”隊伍,以及如何開發(fā)“一問一答”的網(wǎng)絡應用程序。 



      本文來自CSDN博客,轉載請標明出處:http://blog.csdn.net/bitfan/archive/2010/12/24/6097011.aspx

        本站是提供個人知識管理的網(wǎng)絡存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權內(nèi)容,請點擊一鍵舉報。
        轉藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多