• 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];
    }
     
  • 相关阅读:
    C#运行Javascript脚本Utility
    SQL Mail XPs Options
    TSQL AVG Functions
    eclipse编译时过滤SVN版本控制信息方法(转)
    追MM与设计模式
    android的性能调优
    对象的赋值和复制(转)
    SVN Working Copy xxx locked and cleanup failed
    HTTP协议详解(转)
    atoi和itoa函数的实现
  • 原文地址:https://www.cnblogs.com/hanjun/p/2776467.html
Copyright © 2020-2023  润新知