ios開發 網絡編程HTTP/FTP連接


1.CFHTTP

   可以使用CFHTTP API創建HTTP請求,通常HTTP請求方法包括GET、HEAD、PUT、POST、DELETE、TRACR、CONNECT和OPTIONS。使用CFHTTP請求一般4個步驟: 

 

  • 使用CFHTTPMessageCreateRequest函數生成一個CFHTTP消息對象
  • 使用CFHTTPMessageSetBody函數設置消息內容
  • 使用CFHTTPMessageSetHeaderFieldValue函數設置消息頭
  • 使用CFHTTPMessageCopySerializedMessage序列化消息 
   只有http post 需要消息內容,里面是要提交的表單數據。

 

 

示例:創建一個http get請求,序列化后的請求應該通過寫入流(write stream)發送。

CFStringRef requestHeader = CFSTR("Connection");

CFStringRef requestHeaderValue = CFSTR("close");

CFStringRef requestBody = CFSTR("");

 

CFStringRef url = CFSTR("http://www.baidu.com/");

CFStringRef requestMethod = CFSTR("GET");

 

CFURLRef requestURL = CFURLCreateWithString(kCFAllocatorDefault, url, NULL);

CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, requestMethod, requestURL, kCFHTTPVersion1_1);

CFHTTPMessageSetBody(request, requestBody);

CFHTTPMessageSetHeaderFieldValue(request, requestHeader, requestHeaderValue);

 

CFDataRef serializedRequest = CFHTTPMessageCopySerializedMessage(request);


 

      創建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];


 

可選的緩存策略有以下幾種。

(1)NSURLRequestUseProtocolCachePolicy:使用相關協議默認緩存策略。

(2)NSURLRequestReloadIgnoringLocalCacheData: 無論本地緩存是什么,請求都要重新加載數據。

(3)NSURLRequestReloadIgnoringLocalAndRemoteCacheData:不僅要忽略本地緩存,在協議允許的情況下也要忽略遠程代理或中間件的緩存。

(4)NSURLRequestReturnCacheDataElseLoad:優先使用緩存數據,緩存不存在時再去加載請求。

(5)NSURLRequestReturnCacheDataDontLoad:只加載緩存數據,緩存中不存在時也不請求,可理解為離線模式。

(6)NSURLRequestReloadRevalidatingCacheData: 緩存中的數據沒有過期時才加載緩存中的數據,否則請求數據並刷新緩存。


 

 

     創建完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

{
  NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(string);
[data release]; 
 
連接或傳送數據失敗時,didFailWithError方法會被調用,如下:
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
NSLog(@"query failed with error:%@", [error localizedDescription]);
[data release];
}
 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM