與Socket的第一次「約會」

2021-05-23 23:44:55 字數 4517 閱讀 7650

與socket的第一次「約會」

注: 這是乙個針對 網路開發領域初學者 的系列文章,可作為《.net 4.0 物件導向程式設計漫談 》一書的擴充閱讀,寫作過程中我假設讀者可以對照閱讀此書的相關章節,不再浪費筆墨重複介紹相關的內容。

對於其他型別的讀者,除非您已經有相應的.net 技術背景與一定的開發經驗,否則,閱讀中可能會遇到困難。

我希望這系列文章能讓讀者領略到網路開發的魅力!

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

謝謝大家!

金旭亮

《 開篇語—— 無網不勝》

《 ip知多少》

《我在「網」 ** 》

在前面的文章中,我們已經介紹了使用.net平台開發網路應用程式諸如ip位址、網路介面之類的背景知識,本文將介紹.net網路應用程式的主角--socket。如果把socket比喻為一位「美女」,那麼有關她的「愛情故事」實在太多,而本系列後繼的文章,就圍繞著這位「美女」所展開。

1    socket美女的「家庭背景」

socket,中文譯為「套接字」,最早在unix中引入並得到廣泛應用,後來微軟在設計windows時引入了unix中的這個概念和相應的設計理念,並針對windows的特性略作調整,形成了windows平台上的socket,簡稱為「winsock」,並為開發者提供了一整套的api,稱為「windows winsock win32 api 」。

winsock經歷了兩個版本,windows sockets 2是目前用得最多的版本(參看 http://en.wikipedia.org/wiki/winsock ),微軟似乎從來沒有宣布要開發winsock 3,也許「永遠也不會有」了。

圖 1所示為.net平台下網路應用程式的層次架構:

圖 1winsock在底層使用乙個執行於作業系統核心的系統驅動(windows sockets knernel-mode driver)tcpip.sys,由它們負責管理網路連線和緩衝管理。

還有另乙個驅動afd.sys(ancillary function driver for winsock)則用於支援基於 window socket的應用程式,比如ftp、telnet等,被稱為「 windows nt 套接字驅動程式 」。

早期的windows開發者,需要使用c/c++去呼叫winsock,比如mfc就提供了乙個「csocket」類封裝底層的socket。

.net也提供了一組類來封裝winsock win32 api,這些類集中於system.net這一命名空間中,其中的核心型別就是socket。

socket類是對winsock api乙個很淺的封裝,擁有不少方法直接對應於winsock中的c/c++函式,比如poll、select、iocontrol等。

socket有乙個handle屬性,它引用位於作業系統核心的socket核心物件。

了解了socket這位「美女」的「家庭背景」之後,在與她進行第一次「約會」之前,我們不妨弄清楚乙個問題:

現在我們還有必要掌握sokcet程式設計技術嗎?

2    socket是否已人老珠黃?

基於socket開發網路應用程式已經有很多年的歷史了,現在的新技術層出不窮,在.net平台之上,wcf大有「一統江湖」的勢頭,socket是否真的「人老珠黃」?

請看圖 2所示的多層「松花蛋」:

圖 2

3     第乙個socket應用程式

一般我們都將網路應用中用於提供「服務」的一方稱為「服務端應用程式(server)」,另一方訪問這些服務的稱為「客戶端應用程式(client)」。server端和client端的socket用法是不一樣的。

3.1 服務端應用程式

開發網路程式的第一步,是建立socket物件,以下是示例**:

socket newsock = new socket(

addressfamily.internetwork,    //使用ipv4

sockettype.stream, //使用可靠的雙向資料流,不儲存資訊邊界

protocoltype.tcp  //使用tcp協議

);緊接著,需要將socket物件「繫結(bind) 」到乙個「終結點(ipendpoint的例項)」。

ipendpoint ipep = new ipendpoint(ip位址,開啟埠);  //繫結

newsock.bind(ipep);

注意:

wcf中也有「繫結」,但wcf中的「繫結」的含義要豐富得多,它其實是一組特殊的物件,它的主要功能是建立用於實現wcf應用程式間相互通訊的「通道棧」,wcf基類庫中提供了一堆的「繫結」,特定的繫結使用特定的通訊協議和技術,比如nettcpbinding採用tcp協議,netmsmqbinding則使用了微軟訊息佇列。

socket物件繫結網路介面之後,就可以監聽並等待客戶端連線了:

newsock.listen(10);  //開始監聽

socket client = newsock.accept(); //等待客戶端連線

注意:

負責監聽的socket不負責傳送與接收資料,而accept方法返回的socket可以用於接收和傳送資料,但不能用於接收新的連線,同時,其remoteendpoint方法可以獲取遠端客戶端的ip位址和使用的埠

以下**呼叫剛得到的socket物件的receive方法接收客戶端發來的資料:

byte data = new byte[1024];

int r ecv = client.receive(data);

socket.receive方法也是乙個「阻塞」的同步方法,它將收到的資料儲存到乙個位元組陣列中,這個位元組陣列通常稱為「資料緩衝區」。

receive方法的返回值代表接收的資料位元組數。以下**使用這一返回值了解客戶端到底發來了什麼訊息:

console.writeline(encoding.utf8 .getstring(data, 0, recv ));

資料接收完畢,服務端就可以斷開客戶的連線:

client.shutdown(socketshutdown.both);  //通知os,不再接收與傳送資料

client.close();    //關閉socket

完成資料傳送任務之後,注意應該及時地關閉socket。這通常分為兩步:

(1)呼叫shutdown方法通知tcp/ip協議棧傳送所有未傳送的資料,或停止接收資料

(2)呼叫close方法關閉套接字。

socket本身對應著乙個核心物件,它有乙個控制代碼(handle)供作業系統核心進行管理。因此,它不再有用時必須及時地被關閉,否則,有可能會造成嚴重的問題。

socket本身實現了idisposable介面,所以也可以使用using關鍵字實現「自動釋放」:

using (newsock)

//自動關閉newsock

3.2 客戶端應用程式

客戶端應用程式與服務端大同小異:

首先建立好乙個socket物件,然後再呼叫其connect方法建立到服務端的連線,如果之前socket沒有使用bind方法指定乙個埠,connect方法會自動選擇乙個未用的埠:

socket server = new socket( addressfamily.internetwork,

sockettype.stream,  protocoltype.tcp );

server.connect(服務端的ip終結點);

如果connect方法沒有丟擲異常,則表示成功連線伺服器,現在,就可以使用socket物件的send方法傳送資料,資料同樣儲存於乙個資料緩衝區(其實就是乙個byte)中:

server.send(encoding.utf8 .getbytes(要傳送的訊息));

注意這裡選擇的字串編碼方式必須要與服務端一致,否則,將導致服務端無法正確地解碼出字串。

資料傳送完畢,關閉套接字就行了。

3.3 處理網路應用程式中的異常

socket物件的connect、send、receive等方法都有可能出錯,這時,.net基類庫將丟擲乙個socketexception,它實際上封裝的是底層winsock出錯資訊。

每乙個socketexception物件都有乙個對應的錯誤號,其含義是由底層的winsock定的。比如錯誤號為10048的socketexception其含義是:位址已被使用。發生這一異常的原因通常是你嘗試把兩個socket物件繫結到同乙個ipendpoint。

以下是socket網路應用程式中的典型**框架:

socket remote=new socket(……);

trycatch (socketexception e)

,原因:,

nativeerrorcode:,socketerrorcode:", iep.address,

e.message, e.nativeerrorcode, e.socketerrorcode);

}finally

示例專案introducesocket展示了本文所介紹的知識(圖 3)。

圖 3到此,我們與「socket美女」的「第一次約會」到此結束。您對她的第一印象如何?

約會細節第一次

1 手機靜音 2 第一次的約會禮物 3 注意要把指甲剪乾淨 4.幽默 5 口香糖,安全套,手機充滿電,詳細的約會計畫,看好天氣預報,洗好澡,刷好牙,做好髮型,研究好交通。最後,一顆淡定的心,以及提前準備出來的至少10條話題!7 有主見 8 如何浪漫接吻。9 10 可以一起共進晚餐或者在公園散步,晚上...

正常的約會是 第一次約會不像約會而是臨時起約

這心態其實是司馬昭之心。你知道 我知道,女方當然也知道。既然你所有邀約的背後,都需要她日後償付某種代價。那在有這前提的認知下,女人當然會對邀約顯得謹慎的多。所以如果她覺得對你的認識還不足,對於你這個人的性格條件尚有疑慮,還不確定你這人是否能讓她安心下,她為何要 授人以柄 吃飯也好 看電影也好 甚至演...

第一次使用套接字socket程式設計

伺服器端 server new serversocket 18811 18811為埠號這樣就可以建立好乙個socket服務端 socket socket server.accept accept 阻塞型獲取客戶端連線方式 in new inputstreamreader socket.getinpu...