iphone包含了很多架構和庫,從底層的通訊端到不同層次的封裝,可以方便地給程式添加網路功能。
(1)BSD通訊端。最底層的通訊端,這是Unix網路開發常用的API。如果從其他系統移植程式,而程式用的是BSD通訊端,那麼網路部分可以繼續使用這些API。
(2)CFNetwork framework 。CFNetwork 也是比較底層的, 是對BSD通訊端的一個擴充 。它是一個C語言的庫,它是基於BSD通訊端,提供了對網路通訊協定的抽象。這些抽象使得使用者更容易地操作通訊端、處理網路的各種串連。。它整合了run-loop,因此使用CFNetwork不用自己去實現事件迴圈。CFNetwork 還包括了一些網路通訊協定(如HTTP、FTP)的實現,可以在不瞭解這些協議細節的情況下直接使用。
(3) Foundation framework是基於Objectice-C語言的庫,它為CFNetwork API 提供了物件導向的抽象。
(4)CFURL(C)/NSURL(Objective-C)是比較高層的API,它們提供了從Web和FTP伺服器下載檔案或其他資源的一種簡單的方法。其中,CFURL是CFNetwork的一部分,NSURL是Foundation的一部分。
(5)CFNetServices/NSNetServices提供了使用Bonjour註冊和發現網路服務的方法。
總之,CFNetwork framework 和 Foundation framework是最為強大的兩個庫,它們是比較底層、高效,提供的介面也非常豐富。
通訊端
通訊端是網路通訊的基本構件,提供了不同主機間進程雙向通訊的端點。如果電話,只有當一方撥通另一方時,雙方才能建立對話。通過通訊端編程,程式可以跳過複雜的網路底層協議和結構,直接編製與平台無關的應用程式。目前,通訊端已逐漸成為網路編程的通用介面。 通訊端存在於其特定的通訊域(即協議族)中,只有隸屬於同一協議族的通訊端才能建立對話。一般情況下除非通訊協定支援,只有相同類型的通訊端才能相互傳遞資料。從通訊端主要有兩種類型:流式通訊端(TCP)、資料通訊端(UDP)。 流式通訊端(SOCK_STREAM):該類通訊端提供了連線導向的、可靠的、資料無錯並且無重複的資料發送服務,而且發送的資料時按順序被接受的。所有利用該通訊端進行傳遞的資料均被視為連續的位元組流且無長度限制。這對資料的穩定性、正確性和發送/接受順序要求嚴格的應用十分適用,TCP協議使用該類介面,但其對線路的佔用率相對比較高。流式通訊端的實現屢見不鮮,如遠程登入(TELNET)、檔案傳輸通訊協定(FTP)等使用了流式通訊端。 資料通訊端(SOCK_DGRAM):資料通訊端提供了面向不需連線的服務。它獨立地以資料包形式發送資料(資料包長度不能大於32KB),不提供正確性檢查,也不保證各資料包的發送順序,因此可能出現資料的重發、丟失等現象,並且接受順序由具體路由決定。然而,資料報的實現對網路線路佔有率較低,NFS(網路檔案系統)採用此類通訊端,在TCP/IP 協議族中,UDP(UserDatagramProtocol)使用該類介面。
1.CFSocket
CFSocket是對BSD通訊端的一個抽象封裝,它提供了BSD通訊端的幾乎全部功能,還整合了 run-loop。CFSocket可以處理任何類型的通訊端,而不僅僅限於流式通訊端。
(1)建立CFSocket
常用的方法是CFSocketCreate 和CFSocketCreateWithNative。
CFSocketCreate 方法聲明如下:
CFSocketRef CFSocketCreate (
CFAllocatorRef allocator, //指定建立新通訊端的記憶體 Clerk類型,傳入NULL或kCFAllocatorDefault可以使用預設的分配器。一般預設即可。
SInt32 protocolFamily, //指定通訊端的協議族。預設使用PF_INET,也就是平時說的IPV4。指定PF_INET6以使用IPV6協議。
SInt32 socketType, //通訊端類型,SOCK_STREAM或SOCK_DGRAM。
SInt32 protocol, //通訊端使用的協議,IPPROTO_TCP或IPPROTO_UDP。此項需要與通訊端類型一致,設為0取預設值(如果socketType為SOCK_STREAM,此項預設值為IPPROTO_TCP,否則為IPPROTO_UDP)。
CFOptionFlags callBackTypes, //CFSocket提供的run-loop可以在特定件發生時回調指定的函數。這個參數使用了位元遮罩,因此可以使用按位或運算指定多個類型。蘋果公司將一些類型定義為枚舉值如下所示:
枚舉值
enum CFSocketCallBackType {
kCFSocketNoCallBack = 0,
kCFSocketReadCallBack =1,
kCFSocketAcceptCallBack =2,
kCFSocketDataCallBack = 3,
kCFSocketConnectionCallBack = 4,
kCFSocketWriteCallBack =8
};
typedef enum CFSocketCallBackType CFSocketCallBackType;
CFSocketCallBack callout,//指定回呼函數,當指定的事件類型中的一個發生時函數被調用。這樣,不用自己寫迴圈等待串連、發送資料了。
const CFSocketContext *context //儲存與通訊端相關資訊的資料結構,裡面可以包含自訂資料。函數會將裡面的內容拷出來,因此函數調用完後參數指向的記憶體不必再保留。可以為NULL。
);
CFSocketCreateWithNative方法,可以使用一個已經存在的BSD通訊端來建立CRSocket,
CFSocketRef CFSocketCreateWithNative
{
CFAllocatorRef allocator,
CFSocketNativeHandle sock,
CFOptionFlags callBackTypes,
CFSocketCallBack callout,
const CFSocketContext *context
};
2.通訊端函數
建立好CFSocket後,就可以使用它提供的一系列函數了。通過CFSocketNative函數,還可以操作更底層的BSD通訊端。以下幾個函數式CFSocket中常用的。
(1)CFSocketGetNative 返回系統通訊端,通常是int類型的。獲得這個通訊端,可以使用Unix系統原生的通訊端操作。調用setsockopt函數。
(2) CFSocketConnectToAddress 用於將通訊端串連到一個正在監聽的通訊端(伺服器)。
(3)CFSocketCopyAddress 返回CFSocket的地址,可以知道通訊端正在哪個IP地址上監聽。
(4)CFSocketCopyPeerAddress 獲得CFSocket串連到的遠程通訊端的地址。
(5)CFSocketCreateRunLoopSource 為CFSocket建立一個CFRunLoop。
(6)CFSocketSendData 發送資料,需要傳入CFSocket、地址(NULL則發送到通訊端已經串連到的地址)、要發送的資料(CFDataRef類型)、逾時時間。傳回值有kCFSocketSuccess、kCFSocketError和kCFSocketTimeout 3種。
3.回呼函數
函數類型定義
typedef void (*CFSocketCallBack)(
CFSocketRef s,
CFSocketCallBackType callbackType,
CFDataRef address,
const void *data,
void *info
) ;
函式宣告
void CallBackTest
(
CFSocketRef s,
CFSocketCallBackType callbackType,
CFDataRef address,
const void *data,
void *info
) ;
每個回呼函數可以獲得以下資訊,根據類型不同,一些資訊也會不一樣。
(1)CFSocketRefs 事件對應的CFSocket,這樣可以區分不同通訊端產生的事件。
(2)CFSocketCallBackType callbackType 標識哪一種事件發生了。
(3)CFDataRef address 包含底層sockaddr資訊的CFData指標。可以通過這個參數獲得的通訊端串連到的遠程地址。只有在kCFSocketAcceptCallBack和kCFSocketDataCallBack事件發生時才會提供這個參數。
(4)const void *data 根據回調類型指向不同的資料。如果是kCFSocketDataCallBack類型,這個參數為CFDataRef類型,包含接收到的資料;如果是kCFSocketAcceptCallBack類型,這個參數為指向CFSocketNativeHandle的指標;如果為kCFSocketConnectCallBack,串連在後台失敗了,這個參數是指向SInt32類型錯誤碼的一個指標。其他情況這個參數為NULL。
(5)void *info CFSocketContext結構體中的info成員,是自訂資料。CFSocketContext是在建立CFSocket時被指定的。
4.CFSocketContext
它是包含自訂資料及一些回調的結構體。 因為CFSocket通過run-loop非同步通知發生的事件,當有很多串連的時候,如何保持對每個串連相關資料的跟蹤變得困難起來。CFSocketContext允許為通訊端綁定任何類型的資料,每個回呼函數都可以得到這個資料。
CFSocketContext
struct CFSocketContext
{
CFIndex version;//結構體的版本號碼,要求必須為0。
void *info;//指向自訂資料的指標,在CFSocket建立時被關聯的。
CFAllocatorRetainCallBack retain;//對info指標的retain回調,可以為NULL。
CFAllocatorReleaseCallBack release;//對info指標的release回調,可以為NULL。
CGAllocatorCopyDescriptionCallBack copyDescription; //對info指標的copy description回調,可以為NULL。
} ;
typedef struct CFSocketContext CFSocketContext;