詳情請移步github地址查看具體文檔筝闹。https://github.com/huang303513/translateOfAppleDocument
同時也歡迎各位有志之士參與我們的翻譯計劃,github地址:https://github.com/wang820203420/IOS-Developer-library-Chinese/tree/master
---------------------------------以下為翻譯文檔----------------------------------------------------
簡介
重要:這是一個為后面內(nèi)容的準備性的文檔议双。準確的說它會討論一些技術平痰,但不是最終的。蘋果官方提供這個文檔的目的是為了讓你熟悉這個模塊的接口莹规。這里提供的信息可能會改變舞虱,這個文檔里提到的接口信息會在最終的文檔里面確定幼苛。想要了解這個文檔的更新過程焕刮,點擊這里Apple Developer website。進入相關話題的reference library,并且打開它了解溉旋。
這個文檔專門講關于網(wǎng)絡模塊的相關知識观腊。至于在這個文檔里面提到的一些其他話題,我們假設你已經(jīng)熟悉一些基本的網(wǎng)絡概念儡陨。
重要:大部分開發(fā)人員不需要讀這個文檔骗村,并且大部分網(wǎng)絡應用不會需要這個文檔里面的知識(估計意思是大部分app用http)胚股。在你讀這個文檔之前,你需要提前讀Networking Overview以便你更能理解這個文檔里面的內(nèi)容财忽。
這個文檔包含如下幾節(jié):
使用套接字(Socket)和套接字stream---描述了如何使用套接字和stream來做底層網(wǎng)絡編程,從POSIX標準層到Foundation框架層隶校。這個部分解釋了現(xiàn)有的最好解決方法來寫客戶端和服務端深胳。
域名系統(tǒng)(DNS)解析主機---解釋了域名解析系統(tǒng)如何工作舞终,以及如何避開域名解析系統(tǒng)的陷阱余爆。
傳輸層安全(TLS)的正確實現(xiàn)---描述了如何安全的操作傳輸層從而避免讓你的軟件有嚴重的安全問題蛾方。這個部分包括TCP steam(使用CFStream或者NSStream API)和URL請求(使用NSURLConnection API)桩砰。
每個部分都是針對要用到相應知識來編碼的開發(fā)者。
這個文檔假設你已經(jīng)度過下面的文檔或者理解文檔里面的相應的知識:
Networking Overview-講一個互聯(lián)網(wǎng)軟件工作的基本流程枢步,如何避免一些常見的錯誤醉途。
Networking Concepts-描述了以套接字為基礎的網(wǎng)絡操作和基本概念。
這部分講如何用套接字和套接字stream編程,從POSIX協(xié)議層到Foundation框架層劲够。
重要:這部分將描述如何全面使用套接字連接蹲姐,有些應用用更高一級的API更好比如NSURLConnection忙厌。想了解NSURLConnection,讀Networking Overview.
這個部分講一些在Cocoa或者Core Foundation之外的協(xié)議,而且這些協(xié)議是你必須支持的爹土。
在大多數(shù)網(wǎng)絡層中着饥,軟件被分為兩類:客戶端和服務端呵哨。在高級網(wǎng)絡層(high-level API)中拒炎,這個區(qū)分更明顯了。大多數(shù)用高級網(wǎng)絡層的都是客戶端丁侄。然而鸿摇,在低級網(wǎng)絡層中拙吉,這個界限一般很模糊。
套接字和數(shù)據(jù)流(stream)編程一般分為下面的兩類:
. 基于分組的通信(Packet-based communication):程序一般一次操作一個數(shù)據(jù)包佛舱,監(jiān)聽到數(shù)據(jù)包并發(fā)送一個數(shù)據(jù)包作為回應。而且很有可能每個部分都會處理接收到或者發(fā)送的數(shù)據(jù)粟矿。網(wǎng)絡通訊協(xié)議是一致的福压。
. 基于流的客戶端(Stream-based clients):程序通過TCP來接收或者發(fā)送連續(xù)的數(shù)據(jù)流蒙幻。對于這種模式仆救,客戶端和服務端的界限更明顯。客戶端和服務端對數(shù)據(jù)的處理很相似,但是他們構建通訊信道(communication channel)的方式截然不同受裹。
這個部分分為如下幾個部分:
選擇一個API簇(API Family)---描述如何決定使用哪個API簇照藻。
寫一個基于TCP的客戶端---描述如何構建優(yōu)雅地TCP連接到服務器的服務。
寫一個基于TCP的服務端---描述當我們寫服務器的事后,如何監(jiān)聽到來的TCP連接。
工作基于分組的通信的套接字---描述如何在非TCP協(xié)議上工作起愈,比如UDP阐污。
對于基于套接字的鏈接笛辟,你選擇那個API是根據(jù)你是發(fā)送一個鏈接到其他主機還是接受來自其他主機的鏈接杠览。同時也決定于你是否使用TCP或者其他協(xié)議软舌,下面是你做決定的時候需要考慮的一些因素:
.在OS X中黎比,如果你有需要與非MAC平臺的系統(tǒng)通訊,你可以用POSIX C網(wǎng)絡編程API窝革,這樣你就可以在不同平臺共用你的網(wǎng)絡模塊漆诽。如果你的程序是基于Core Foundation或者Cocoa (Foundation)的運行時循環(huán)(run loop)蚪腐,你也可以使用Core Foundation的 CFStream API來集成POSIX標準的網(wǎng)絡模塊。另一方面泡一,如果你用GCD帖蔓,你可以添加一個套接字作為調度源(dispatch source).
.在iOS中塑娇,POSIX標準沒有被支持埋酬,因為這個標準不支持移動蜂窩網(wǎng)絡(cellular radio)或者指定的VPN耳标。通常情況下邑跪,你需要從平常的數(shù)據(jù)處理行數(shù)中分開網(wǎng)絡模塊并且用更高一級的API重寫網(wǎng)絡模塊的代碼。
注意:如果你用POSIX標準的網(wǎng)絡模塊代碼宋距,你需要注意到POSIX標準的網(wǎng)絡API不是協(xié)議無關的(protocol-agnostic)(你必須處理IPV4和IPV6的不同)诱篷。這是一個IP網(wǎng)絡層的一個API而一個名字相關(connect-by-name)API,這意味著你必須做一些額外的工作迎吵,如果你想實現(xiàn)一些相同的內(nèi)部鏈接特性和更高一級的API的健壯性問題蔫巩。在你決定使用POSIX標準的網(wǎng)絡模塊以前拦宣,你需要讀Avoid Resolving DNS Names Before Connecting to a Host
.對于監(jiān)聽一個端口的守護進程、服務菊值、非TCP的鏈接外驱,使用POSIX標準或者Core Foundation(CFSocket)的網(wǎng)絡模塊API育灸。
.對于用Objective-C寫的客戶端,用它的Foundation框架的API昵宇。Foundation框架定義了針對URL鏈接磅崭、套接字流、網(wǎng)絡服務和其他網(wǎng)絡任務的高級接口瓦哎。在iOS和OS X中砸喻,這個框架同時也是最基礎的、UI無關的Objective-C框架蒋譬,提供運行時循環(huán)的各種操作割岛、字符串處理、集合類犯助、文件訪問等等癣漆。
. 如果客戶端是C語言寫的。用Core Foundation的網(wǎng)絡API也切,這個框架和 CFNetwork框架是兩個基于C語言的框架扑媚。他們一起定義了一些Foundation框架用到的結構體和函數(shù)。
注意:在OS X中雷恃,CFNetwork框架是Core Services框架的子框架疆股;在iOS中,CFNetwork框架是一個獨立的一級框架倒槐。
你編寫友好的網(wǎng)絡連接接口的方式是取決于你選擇的編程語言旬痹、連接的類型(TCP,UDP等等)、是否要和其他平臺分享相同的代碼讨越。
.在Objective-C中用NSStream來建立連接两残。
如果你要連接到一個主機,新建一個CFHost對象(不是NSHost-他們不能無縫橋接(toll-free bridged)),用CFStreamCreatePairWithSocketToHost和CFStreamCreatePairWithSocketToCFHost來開始一個套接字連接到指定主機和端口把跨,并且關聯(lián)兩個CFStream對象人弓。你也可以用NSStream對象。
你也可以用 CFStreamCreatePairWithSocketToNetService 函數(shù)來連接到一個Bonjour service(好像用于蘋果設備之間的通訊)着逐。讀Discovering and Advertising Network Services來獲取更多信息崔赌。
.用POSIX標準如果需要支持跨平臺。
如果你寫的代碼只用與蘋果平臺耸别,name你要避免使用POSIX標準的代碼健芭,因為他們和高層的協(xié)議比起來,他們更難以操作秀姐。然而慈迈,如果你寫的網(wǎng)絡模塊代碼必須在不同平臺分享的話,你可以用POSIX標準的網(wǎng)絡API從而你能復用同樣的代碼省有。
千萬別在主線程使用POSIX協(xié)議網(wǎng)絡的同步API痒留。如果你要用這種API谴麦,你必須在一個單獨的線程里。
注意:POSIX協(xié)議網(wǎng)絡不支持iOS平臺的蜂窩網(wǎng)絡狭瞎,因為這個原因细移,iOS平臺不需要POSIX標準的網(wǎng)絡API。
下面將講NSStream的用法熊锭,除非特別標明弧轧,CFStream API一般都有一個同樣名字的函數(shù),而且實現(xiàn)也相似。
要了解更多POSIX標準的套接字API碗殷,讀UNIX Socket FAQ在http://developerweb.net/.
通常情況下精绎,建立一個TCP鏈接到其他主機用的是數(shù)據(jù)流。Streams自動處理TCP鏈接面臨的挑戰(zhàn)锌妻。比如代乃,數(shù)據(jù)流提供了通過主機名(hostname)鏈接的能力,在iOS中仿粹,數(shù)據(jù)流會自動喚醒設備得蜂窩模式或者指定的VPN當需要的時候(不像CFSocket 或者 BSD Socket)搁吓。相比于底層協(xié)議,Streams更相似Cocoa框架的接口吭历,和Cocoa的文件操作API有很大的相似性堕仔。
你獲取或者發(fā)送數(shù)據(jù)流取決于你是否要被鏈接或者主動鏈接到一個主機。
.如果你已經(jīng)知道了一個主機的DNS名字或者IP地址晌区,使用 Core Foundation來讀取或者發(fā)送數(shù)據(jù)流通過 CFStreamCreatePairWithSocketToHost函數(shù)摩骨。你可以充分利用CFStream和NSStream的無縫轉換。把CFReadStreamRef和CFWriteStreamRef對象轉換為NSInputStream和 NSOutputStream對象朗若。
.如果你想通過CFNetServiceBrowser對象來鏈接到一個主機恼五,你可以通過CFStreamCreatePairWithSocketToNetService函數(shù)來接收或者發(fā)送數(shù)據(jù)。讀取Discovering and Advertising Network Services
當你得到輸出路和輸入流以后哭懈,在沒有用arc的情況下你必須馬上占有他們灾馒,把他們引用到一個NSInputStream和NSOutputStream對象,并且設置他們的代理對象(這個對象需要實現(xiàn)NSStreamDelegate協(xié)議)遣总。通過調用open方法在當前運行時循環(huán)上執(zhí)行他們你虹。
注意:如果你需要同時處理一個以上鏈接,你需要區(qū)分是那個輸入流和輸出流關聯(lián)彤避。最直接的方式你新建一個鏈接對象同時擁有輸入流和輸出流的引用,并且把這個對象設置為他們的代理夯辖。
當NSOutputStream對象的代理方法stream:handleEvent:被調用了琉预,并且設置streamEvent參數(shù)的值為NSStreamEventHasSpaceAvailable,最后調用 write:maxLength:來發(fā)送數(shù)據(jù)蒿褂。write:maxLength:方法要么返回發(fā)送的數(shù)據(jù)的長度圆米,要么返回一個負數(shù)表示失敗卒暂。如果這個方法返回的數(shù)據(jù)的長度小于你嘗試發(fā)送的數(shù)據(jù)的長度,你必須把沒有發(fā)送的那部分數(shù)據(jù)發(fā)送出去通過調用NSStreamEventHasSpaceAvailable事件娄帖。如果發(fā)生錯誤也祠,你需要調用 streamError方法來確認是哪里發(fā)生了錯誤。
當NSInputStream對象的代理方法stream:handleEvent:被調用了近速,并且設置streamEvent參數(shù)的值為NSStreamEventHasBytesAvailable诈嘿。你可以通過 read:maxLength:方法來讀取接收到得數(shù)據(jù)。這個方法返回接收到得數(shù)據(jù)的長度或者返回一個負數(shù)表示接收失敗削葱。
如果接收到的數(shù)據(jù)的長度小于你需要的長度奖亚,你必須持有數(shù)據(jù)并且等待直到你收到所有的數(shù)據(jù)。如果發(fā)生錯誤析砸,你需要調用 streamError方法來確認是哪里發(fā)生了錯誤昔字。
如果鏈接的另一端中斷了鏈接:
你的鏈接代理方法stream:handleEvent:被調用。并且streamEvent參數(shù)設置為NSStreamEventHasBytesAvailable首繁。如果你去讀取接收到的數(shù)據(jù)作郭,你會發(fā)現(xiàn)長度為零。
你的代理方法stream:handleEvent: 會被調用弦疮。并且streamEvent參數(shù)被設置為 NSStreamEventEndEncountered夹攒。
當上面兩個事件的其中一個發(fā)生了,代理方法需要處理鏈接操作結束工作和清理工作挂捅。
當結束一個鏈接的時候芹助,我們首先要把它從當前運行時循環(huán)移除,設置鏈接的代理為nil(代理對象并沒有被retain)闲先。通過close方法關閉與鏈接關聯(lián)的兩個數(shù)據(jù)流状土,最后在釋放者兩個數(shù)據(jù)流對象(如果你沒有使用ARC)或者把他們設置為nil。這就是通常的關閉鏈接的方式伺糠。然而蒙谓,如果有下面兩種情況你需要手動關閉鏈接:
對于一個數(shù)據(jù)流,如果你通過 setProperty:forKey: 方法設置 kCFStreamPropertyShouldCloseNativeSocket屬性值為kCFBooleanFalse训桶。
如果你通過CFStreamCreatePairWithSocket方法創(chuàng)建以BSD套接字為基礎的數(shù)據(jù)流累驮。一般情況下,數(shù)據(jù)流是在一個系統(tǒng)套接字(native socket)的基礎上創(chuàng)建的舵揭,并且關閉的時候不會關閉底層的套接字谤专。但是,你也可以設置自動關閉底層套接字通過設置kCFStreamPropertyShouldCloseNativeSocket屬性值為kCFBooleanTrue午绳。
要了解更多, 讀[Stream Programming Guide]和[Using NSStreams For A TCP Connection Without NSHost]中的[Setting Up Socket Streams]部分, 或者下載SimpleNetworkStreams工程來看看.
下一步將翻譯socket的服務器部分置侍。