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