1.CFHTTP
可以使用CFHTTP API創建HTTP請求,通常HTTP請求方法包括GET、HEAD、PUT、POST、DELETE、TRACR、CONNECT和OPTIONS。使用CFHTTP請求一般4個步驟:
- 使用CFHTTPMessageCreateRequest函數生成一個CFHTTP消息對象
- 使用CFHTTPMessageSetBody函數設置消息內容
- 使用CFHTTPMessageSetHeaderFieldValue函數設置消息頭
- 使用CFHTTPMessageCopySerializedMessage序列化消息
創建HTTP相應的步驟與創建請求的方法差不多,不同之處是用CFHTTPMessageCreateResponse函數代替CFHTTPMessageCreateRequest。
可以使用一個CFReadStream對象來序列化並發送CFHTTP請求。當使用CFReadStream對象時,打開讀取流的同時消息會被序列化並發送,這樣可以方便地獲取響應。如下:
CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, requestURL, kCFHTTPVersion1_1);
CFHTTPMessageSetBody(request, requestBody);
CFHTTPMessageSetheaderFieldValue(request, requestHeader, requestHeaderValue);
CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request);
CFReadStreamOpen(readStream);
調用CFReadStreamCopyProperty 可以從讀取流獲取響應消息,代碼如下:
CFHTTPMessageRef response = CFReadStreamCopyProperty(readStream, kCFStreamPropertyHTTPResponseHeader);
使用CFHTTPMessageCopyResponseStatusLine函數獲得完整的狀態行,如下:
CFStringRef statusLine = CFHTTPMessageCopyResponseStatusLine(response);
或者,使用CFHTTPMessageGetResponseStatusCode函數獲取狀態碼,如下:
UInt32 errCode = CFHTTPMessageGetResponseStatusCode(response);
為了獲取返回的數據,可以使用CFReadStreamSetClient方法設置回調函數,將readStream加到run loop中。在回調函數將每次讀取的數據存起來(比如,有一個NSMutableData類型的變量data),讀完后處理數據,代碼如下:
if(kCFStreamEventHasBytesAvailable == eventType)
{
UInt8 buff[255];
int length = CFReadStreamRead(stream, buff, 254);
[data appendBytes:buff length:length];
if(kCFStreamEventEndEncountered == eventType)
{
//讀取已完成,處理讀取的數據
}
}
如果接收數據是中文字符串,注意在創建NSString時選擇編碼,比如UTF8或GB2312編碼,如下所示:
NSString *string = [[NSString alloc] initWithData:data encoding:0x80000632];//GB2312編碼
當使用CFReadStreamCreateForHTTPRequest創建讀取流時,流的重定向默認是被禁止的。如果請求連接被重定向,會導致一個錯誤,它的狀態碼為300~307。如果收到一個重定向錯誤,需要關閉這個流,然后重新創建一個流,啟用重定向並打開流。如下:
CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request);
if(CFReadStreamSetProperty(readStream, kCFStreamPropertyHTTPShouldAutoredirect, kCFBooleanTrue) == false)
{
//出錯處理
}
CFReadStreamOpen(myReadStream);
2.CFFTP
CFFTP也使用CFReadStream來傳送FTP數據。使用CFReadStreamCreateWithFTPURL方法來創建FTP請求,這樣會同時創建一個CFReadStreamRef對象來讀取FTP服務器發送的數據,代碼如下:
CFStringRef url = CFSTR("ftp://ftp.example.com/file.txt");
CFURLRef requestURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);
CFReadStreamRef readStream = CFReadStreamCreateWithFTPURL(kCFAllocatorDefault, requestURL);
下一步,使用CFReadStreamSetClient方法設置回調函數來讀取數據,然后把readStream加到程序的run loop中。
如果FTP需要使用用戶名和密碼認證,通過CFReadStreamSetProperty方法設置kCFStreamPropertyFTPUserName和kCFStreamPropertyFTPPassword屬性。
要將文件下載到本地,可以使用CFWriteStreamCreateWithFile方法創建一個指向本地文件的寫入流,將接收到的數據寫入。
上傳文件和下載文件差不多,只不過把讀取流和寫入流反過來用,使用CFWriteStreamCreateWithFTPURL方法創建寫入流,使用CFReadStreamCreateWithFile創建讀取流。
創建遠程目錄的方法與上傳文件類似,只不過將CFURL對象設置一個路徑而不是文件。
獲取目錄列表的方法與下載文件類似,數據讀取到緩存后使用CFFTPCreateParsedResourceListing,方法對讀取進行解析。
3.NSURLConnection
CFNetwork是比較底層的接口,雖然用起來比較靈活,但並不好用。多數程序僅僅需要創建簡單的請求來獲取互聯網上的一個文件,那么使用NSURLConnection要更加方便,因為不用跟套接字、流還有回調函數打交道,取而代之的是更熟悉的委托機制。
創建一個NSURL對象:
NSNRL *url = [NSURL URLWithString:@"http://www.baidu.com/"];
NSURL對象是用來創建NSURLRequest對象的,如下:
NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoadtimeoutInterval:60.0];
創建完NSURLRequest對象后就可以創建NSURLConnection對象了,如下:
NSURLConnection *connection = [[NSRULConnection alloc] initWithRequest:request delegate:self];
這個是異步調用,NSURLConnection會在后台發送請求,通過設置委托參數,有數據時會收到通知。由一些委托方法來處理連接是過程中的不同事件。
當服務主機有響應將要開始發送數據時,didReceiveResponse:方法會被調用。這里可以做一些初始化的工作,比如有一個NSMutableData類型的data對象來存儲數據,在這里可以把對象長度設為0,如下所示
-(void) connection:(NSURLConnection *)connection didReceiveRespose:(NSURLResonse *)response
{
[data setLength:0];
}
當接收到數據時,didReceiveData:方法會被調用。這里可以把數據加到NSMutableData對象的后面,如下:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)incomingData
{
[data appendData:incomingData];
}
當數據加載完成時會調用connecitionDidFinshLoading:方法,處理傳入的數據。這里以字符串處理為例,示例應用中傳入的可能是圖片或其他任何類型的對象。
- (void)connectionDidFinishLoading:(NSURLConnection *)connection