使用CFHTTP API创建HTTP请求 并加入代理服务器

来源:互联网 发布:图书管理系统c语言代码 编辑:程序博客网 时间:2024/04/30 03:18

当时因为公司项目需求,需要在访问服务器数据的时候加入代理服务器,当时访问数据用的是hessian的官方类库,其中访问数据部分集成的是【Foundation.Framework】的NSURLConnection类,但是NSURLConnection是没有相关代理部分的封装方法的,经过查看资料,发现第三方库ASIHTTPRequest是有相关代理的设置功能,而且是代理部分是基于CFNetwork API实现的封装,经过对ASIHTTPRequest源码和CFNetwork API的研究,发现其实ASIHTTPRequest关于设置代理是对数据流做了处理,于是剥离出代理部分相关代码,替换hessian类库中NSURLConnection访问网络部分,成功实现CFHTTP设置代理。

使用CFHTTP请求一般为2个步骤,数据的请求和数据的处理回调

 1.  数据的请求

  • 使用CFHTTPMessageCreateRequest函数生成一个CFHTTP消息对象。
  • 使用CFReadStreamCreateForHTTPRequest创建生成流来发送数据。
  • 使用CFReadStreamSetProperty对流的代理进行设置。
  • 使用CFStreamClientContext和CFReadStreamSetClient来创建和设置回调。
  • 把流加入队列,然后使用CFReadStreamOpen来发送请求。


- (void)viewDidLoad{    [super viewDidLoad];    self.cancelledLock=[[[NSRecursiveLock alloc]init]autorelease];    NSURL *url = [NSURL URLWithString:@"访问服务器地址"];    request=[NSURLRequest requestWithURL:url];      [self proxy_hard];}

-(void)proxy_hard{    static const CFOptionFlags kNetworkEvents =  kCFStreamEventHasBytesAvailable | kCFStreamEventEndEncountered | kCFStreamEventErrorOccurred;       NSString *proxyHost=@"61.50.245.163";    int proxyPort=8000;        NSString *hostKey;    NSString *portKey;           hostKey = (NSString *)kCFStreamPropertyHTTPProxyHost;    portKey = (NSString *)kCFStreamPropertyHTTPProxyPort;        CFHTTPMessageRef request_message;        NSMutableDictionary *proxyToUse = [NSMutableDictionary dictionaryWithObjectsAndKeys:proxyHost,hostKey,[NSNumber numberWithInt:proxyPort],portKey,nil];        request_message = CFHTTPMessageCreateRequest(kCFAllocatorDefault, (CFStringRef)(@"GET"), (CFURLRef)request.URL, kCFHTTPVersion1_1);        readStream=(NSInputStream *)CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request_message) ;        //readStream=request.HTTPBodyStream;        CFReadStreamSetProperty((CFReadStreamRef)readStream, kCFStreamPropertyHTTPProxy, proxyToUse);    CFStreamClientContext ctxt = {0, self, NULL, NULL, NULL};    CFReadStreamSetClient((CFReadStreamRef)readStream, kNetworkEvents, ReadStreamClientCallBack, &ctxt);    [readStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];           CFReadStreamOpen((CFReadStreamRef)readStream);}


2. 请求回调参数类型

  • kCFStreamEventHasBytesAvailable   //有数据可以接收
  • kCFStreamEventEndEncountered  //接收完成
  • kCFStreamEventErrorOccurred //发生错误


-(void)handleNetworkEvent:(CFStreamEventType)type{    [[self cancelledLock] lock];CFRetain(self);    // Dispatch the stream events.    switch (type) {        case kCFStreamEventHasBytesAvailable:            [self handleBytesAvailable];            break;                    case kCFStreamEventEndEncountered:            [self handleStreamComplete];            break;                    case kCFStreamEventErrorOccurred:            [self handleStreamError];            break;                    default:            break;    }[[self cancelledLock] unlock];CFRelease(self);}//回调函数 有数据可以接收- (void)handleBytesAvailable{    long long bufferSize = 16384;if (contentLength > 262144) {bufferSize = 262144;} else if (contentLength > 65536) {bufferSize = 65536;}    UInt8 buffer[bufferSize];    NSInteger bytesRead = [readStream read:buffer maxLength:sizeof(buffer)];    NSData *inflatedData = nil;    [self setTotalBytesRead:[self totalBytesRead]+bytesRead];    inflatedData = [NSData dataWithBytes:buffer length:bytesRead];     NSLog(@"inflatedData:%@",[[NSString alloc]initWithData:inflatedData encoding:NSUTF8StringEncoding]);}//回调函数 接收完成- (void)handleStreamComplete{}//回调函数 发生错误- (void)handleStreamError{    }



示例:创建一个http get 或post 请求

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);

0 0
原创粉丝点击