国产一级a片免费看高清,亚洲熟女中文字幕在线视频,黄三级高清在线播放,免费黄色视频在线看

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
與Socket的第一次“約會(huì)”
.NET 4.0網(wǎng)絡(luò)開(kāi)發(fā)入門(mén)之旅--

與Socket的第一次“約會(huì)” 

注: 

    這是一個(gè)針對(duì) 網(wǎng)絡(luò)開(kāi)發(fā)領(lǐng)域初學(xué)者 的系列文章,可作為《.NET 4.0 面向?qū)ο缶幊搪?》一書(shū)的擴(kuò)充閱讀,寫(xiě)作過(guò)程中我假設(shè)讀者可以對(duì)照閱讀此書(shū)的相關(guān)章節(jié),不再浪費(fèi)筆墨重復(fù)介紹相關(guān)的內(nèi)容。 

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

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

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

      本文如有錯(cuò)誤,敬請(qǐng)回貼指正。 

    謝謝大家! 

 

                                                          金旭亮 

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

點(diǎn)擊以下鏈接閱讀本系列前面的文章: 

 

《 開(kāi)篇語(yǔ)—— 無(wú)網(wǎng)不勝》 
《 IP知多少》 

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

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

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


 


圖 1


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

    提示: 
    有關(guān)系統(tǒng)核心對(duì)象(Kernel Object)的通俗解釋,請(qǐng)參看《.NET 4.0面向?qū)ο缶幊搪?》中的15.1.2節(jié)《操作系統(tǒng)的進(jìn)程管理》 

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

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

    提示: 
    強(qiáng)烈建議讀者仔細(xì)閱讀《.NET 4.0面向?qū)ο缶幊搪?》中的第10章《異步編程模式》,以提前掌握.NET異步編程的基礎(chǔ)知識(shí)與基本技能,否則,后面的文章可以不用看了。 

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

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

 

圖 2 

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


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

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

    緊接著,需要將Socket對(duì)象“綁定(Bind) ”到一個(gè)“終結(jié)點(diǎn)(IPEndPoint的實(shí)例)”。

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    using (newsock)
    {
           ……
    }  //自動(dòng)關(guān)閉newsock 

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

    Socket server = new Socket( AddressFamily.InterNetwork,
                    SocketType.Stream,  ProtocolType.Tcp );
    server.Connect(服務(wù)端的IP終結(jié)點(diǎn));

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

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

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

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

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

 

圖 3



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

點(diǎn)擊下載本文示例 


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


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



本文來(lái)自CSDN博客,轉(zhuǎn)載請(qǐng)標(biāo)明出處:http://blog.csdn.net/bitfan/archive/2010/12/24/6097011.aspx
本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)
打開(kāi)APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
手工查殺木馬病毒13—Autoruns-5
用WINSOCK實(shí)現(xiàn)聊天室的VC++程序設(shè)計(jì)
Windows Socket編程簡(jiǎn)介_(kāi)網(wǎng)絡(luò)技術(shù)_程序開(kāi)發(fā)_遠(yuǎn)播教育網(wǎng)
孫鑫VC視頻教程筆記之第十六課(下)“異步套接字編程”
Windows Sockets網(wǎng)絡(luò)編程讀書(shū)筆記(及簡(jiǎn)單C/S實(shí)現(xiàn))
用Winsock控件實(shí)現(xiàn)點(diǎn)對(duì)點(diǎn)通信
更多類似文章 >>
生活服務(wù)
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服