美文网首页
iOS网络编程

iOS网络编程

作者: CoderRH | 来源:发表于2018-11-05 16:22 被阅读3次

    一、URL

    • URL的全称是Uniform Resource Locator(统一资源定位符),通过1个URL,能找到互联网上唯一的1个资源,URL就是资源的地址、位置,互联网上的每个资源都有一个唯一的URL

    • 的基本格式 = 协议://主机地址/路径,示例:
      http://www.baidu.com/img/logo.png
      http://111.111.111.111/img/bdlogo.gif

    • 协议、主机地址、路径的含义:
      协议:不同的协议,代表着不同的资源查找方式、资源传输方式
      主机地址:存放资源的主机(服务器)的IP地址(域名)
      路径:资源在主机(服务器)中的具体位置

    二、HTTP协议

    1.HTTP协议简介
    • HTTP的全称是Hypertext Transfer Protocol,超文本传输协议
    • 规定客户端和服务器之间的数据传输格式
    • 让客户端和服务器能有效地进行数据沟通
    2.HTTP协议特点
    • 简单快速:因为HTTP协议简单,所以HTTP服务器的程序规模小,因而通信速度很快
    • 灵活:HTTP允许传输各种各样的数据
    • HTTP 0.9和1.0使用非持续连接:限制每次连接只处理一个请求,服务器对客户端的请求做出响应后,马上断开连接,这种方式可以节省传输时间
    3.HTTP协议的请求方法
    • 在HTTP/1.1协议中,定义了8种发送http请求的方法:GET、POST、OPTIONS、HEAD、PUT、DELETE、TRACE、CONNECT、PATCH
    • PUT :增、DELETE :删、POST:改、GET:查
    • 最常用的是GET和POST(实际上GET和POST都能办到增删改查)
    4.GET和POST
    4.1、GET
    • 在请求URL后面以?的形式跟上发给服务器的参数,多个参数之间用&隔开,比如:http://ww.test.com/login?username=123&pwd=234&type=JSON
    • 由于浏览器和服务器对URL长度有限制,因此在URL后面附带的参数是有限制的,通常不能超过1KB
    • 如果仅仅是索取数据(数据查询),建议使用GET
    4.2、POST
    • 发给服务器的参数全部放在请求体中
    • 理论上,POST传递的数据量没有限制(具体还得看服务器的处理能力)
    • 如果要传递大量数据,比如文件上传,只能用POST请求
    • GET的安全性比POST要差些,如果包含机密\敏感信息,建议用POST
    • 如果是增加、修改、删除数据,建议使用POST
    5、iOS中发送HTTP请求的方案
    5.1、苹果原生(自带)
    • NSURLConnection:用法简单,最古老最经典最直接的一种方案【坑比较多】
    • NSURLSession:功能比NSURLConnection更加强大,苹果目前比较推荐使用这种技术【2013推出,iOS7开始出的技术】
    • CFNetwork:NSURL*的底层,纯C语言
    5.2、第三方框架
    • ASIHttpRequest:外号“HTTP终结者”,功能极其强大,可惜早已停止更新
    • AFNetworking:简单易用,提供了基本够用的常用功能,维护和使用者多
    • MKNetworkKit:简单易用,维护和使用者少
    6、HTTP通信过程
    6.1、请求
    • HTTP协议规定:1个完整的由客户端发给服务器的HTTP请求中包含以下内容
    • 请求头:包含了对客户端的环境描述、客户端请求信息等
    • GET /minion.png HTTP/1.1 // 包含了请求方法、请求资源路径、HTTP协议版本
    • Host: 120.25.226.186:32812 // 客户端想访问的服务器主机地址
    • User-Agent: Mozilla/5.0 // 客户端的类型,客户端的软件环境
    • Accept: text/html, / // 客户端所能接收的数据类型
    • Accept-Language: zh-cn // 客户端的语言环境
    • Accept-Encoding: gzip // 客户端支持的数据压缩格式
    • 请求体:客户端发给服务器的具体数据,比如文件数据(POST请求才会有)
    6.2、响应
    • 客户端向服务器发送请求,服务器应当做出响应,即返回数据给客户端
    • HTTP协议规定:1个完整的HTTP响应中包含以下内容:
    • 响应头:包含了对服务器的描述、对返回数据的描述:
    • HTTP/1.1 200 OK // 包含了HTTP协议版本、状态码、状态英文名称
    • Server: Apache-Coyote/1.1 // 服务器的类型
    • Content-Type: image/jpeg // 返回数据的类型
    • Content-Length: 56811 // 返回数据的长度
    • Date: Mon, 23 Jun 2014 12:54:52 GMT // 响应的时间
    • 响应体:服务器返回给客户端的具体数据,比如文件数据
    6.3、常见的响应状态码
    常见服务器响应的状态码

    三、NSURLConnection

    1、NSURLConnection的使用步骤
    • 创建一个NSURL对象,设置请求路径
    • 传入NSURL创建一个NSURLRequest对象,设置请求头和请求体(POST请求的时候使用NSMutableURLRequest设置请求体,GET和POST请求头已经默认设置好了)
    • 使用NSURLConnection发送请求
    1.1、NSURLConnection使用图示
    NSURLConnection使用图示
    2.NSURLConnection实际使用
    2.1、NSURLConnection的基本使用
    //发送异步请求:不会卡住当前线程
    - (void)async{
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
            NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
            NSLog(@"%@", string);
            //获取响应头信息
            NSHTTPURLResponse *r = (NSHTTPURLResponse *)response;
            NSLog(@"%zd %@", r.statusCode, r.allHeaderFields);
        }];
    }
    
    //发送同步请求:卡住当前线程,直到请求完成
    - (void)sync{
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=345"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSHTTPURLResponse *response = nil;
        NSError *error = nil;
        NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
        
        NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
        NSLog(@"%@ %@", string, response.allHeaderFields);
    }
    
    2.2、NSURLConnection的代理方式:拿到connection对象调用cancel方法可以取消请求
    - (void)delegateAysnc{
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520it&pwd=520it"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        
        [NSURLConnection connectionWithRequest:request delegate:self];//自动请求
        //[[NSURLConnection alloc] initWithRequest:request delegate:self];//自动请求
    
        //startImmediately:YES:立即自动请求,NO:调用conn的start方法才会请求
        //NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];
    }
    
    //<NSURLConnectionDataDelegate>
    // 接收到服务器的响应
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
    }
     //接收到服务器的数据(如果数据量比较大,这个方法会被调用多次)
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    }
    //服务器的数据成功接收完毕
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection{
    }
    //请求失败(比如请求超时)
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    }
    
    2.3、NSMutableURLRequest简介
    //设置请求超时等待时间(超过这个时间就算超时,请求失败)
    - (void)setTimeoutInterval:(NSTimeInterval)seconds;
    
    //设置请求方法(比如GET和POST)
    - (void)setHTTPMethod:(NSString *)method;
    
    //设置请求体
    - (void)setHTTPBody:(NSData *)data;
    
    //设置请求头
    - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field;
    
    
    2.4、NSURLConnection发送POST请求
    - (void)sendPOSTRequest {
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        request.HTTPMethod = @"POST";
        request.HTTPBody = [@"username=520it&pwd=520it" dataUsingEncoding:NSUTF8StringEncoding];
        request.timeoutInterval = 5;
        // 设置请求头
        //[request setValue:@"iOS 9.0" forHTTPHeaderField:@"User-Agent"];
        
        // 3.发送请求
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        }];
    }
    
    2.5、URL中文转码
    //URL中包含中文的话需要进行转码,否则识别不了
    - (nullable NSString *)stringByAddingPercentEscapesUsingEncoding:(NSStringEncoding)enc;
    

    四、JSON&XML

    1、JSON
    • 第三方框架:JSONKit、SBJson、TouchJSON(性能从左到右,越差)
    • 苹果原生(自带):NSJSONSerialization(性能最好)
    + (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
    + (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error;
    
    2、XML
    • 全称是Extensible Markup Language,译作“可扩展标记语言”,跟JSON一样,也是常用的一种用于交互的数据格式,一般也叫XML文档(XML Document)
    • 一个常见的XML文档一般由以下部分组成:
      文档声明
      元素(Element)
      属性(Attribute)
    2.1、文档声明
    • 在XML文档的最前面,必须编写一个文档声明,用来声明XML文档的类型
    • 最简单的声明:
      <?xml version="1.0" ?>
    • 用encoding属性说明文档的字符编码:
      <?xml version="1.0" encoding="UTF-8" ?>
    2.2、元素(Element)
    • 一个元素包括了开始标签和结束标签
    • 拥有内容的元素:<video>小黄人</video>
    • 没有内容的元素:<video></video>
    • 没有内容的元素简写:<video/>
    • 一个元素可以嵌套若干个子元素(不能出现交叉嵌套)


      元素嵌套
    • 规范的XML文档最多只有1个根元素,其他元素都是根元素的子孙元素
    2.3、属性(Attribute)
    • 一个元素可以拥有多个属性
      <video name="小黄人 第01部" length="30" />
    • video元素拥有name和length两个属性
    • 属性值必须用 双引号"" 或者 单引号'' 括住
    3、XML的解析
    3.1、DOM&SAX
    • DOM:一次性将整个XML文档加载进内存,比较适合解析小文件
    • SAX:从根元素开始,按顺序一个元素一个元素往下解析,比较适合解析大文件
    3.2、解析方式
    • 苹果原生
      NSXMLParser:SAX方式解析,使用简单
    • 第三方框架
      libxml2:纯C语言,默认包含在iOS SDK中,同时支持DOM和SAX方式解析
      GDataXML:DOM方式解析,由Google开发,基于libxml2
    • XML解析方式的选择建议
      大文件:NSXMLParser、libxml2
      小文件:GDataXML、NSXMLParser、libxml2
    3.3、GDataXML的配置

    3.3.1、GDataXML下载地址 密码:hsfn
    3.3.2、导入libxml2库:

    导入libxml2库
    3.3.3、设置libxml2的头文件搜索路径(为了能找到libxml2库的所有头文件):在Head Search Path中加入/usr/include/libxml2
    3.3.4、设置链接参数(自动链接libxml2库:在Other Linker Flags中加入-lxml2
    3.4、NSXMLParser解析示例:
    //XML大致格式
    <videos>
        <video id="1" name="xxx" length="xxx" url="xxx" image= "xxx"/>
        <video id="2" name="xxx" length="xxx" url="xxx" image= "xxx"/>
        <video id="3" name="xxx" length="xxx" url="xxx" image= "xxx"/>
    </videos>
    
    - (void)NSXMLParserTest {
        [super viewDidLoad];
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
            NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data];
            parser.delegate = self;
            [parser parse];//会阻塞当前线程
        }];
    }
    
    #pragma mark - <NSXMLParserDelegate>
    
    //解析到某个元素的结尾(比如解析</videos>)
    - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
    }
    
    // 解析到某个元素的开头(比如解析<videos>)
    - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict{
        if ([elementName isEqualToString:@"videos"]) return;
        VideoModel *video = [VideoModel objectWithKeyValues:attributeDict];
        [self.videos addObject:video];
    }
    
    
    //开始解析XML文档
    - (void)parserDidStartDocument:(NSXMLParser *)parser{
    }
    
    //解析完毕
    - (void)parserDidEndDocument:(NSXMLParser *)parser{
    }
    
    3.5、GDataXML解析示例:
    //XML大致格式
    <videos>
        <video id="1" name="xxx" length="xxx" url="xxx" image= "xxx"/>
        <video id="2" name="xxx" length="xxx" url="xxx" image= "xxx"/>
        <video id="3" name="xxx" length="xxx" url="xxx" image= "xxx"/>
    </videos>
    
    - (void)GDataXMLTest {
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/video?type=XML"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
            // 加载整个文档
            GDataXMLDocument *doc = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
            
            // 获得所有video元素
            NSArray *elements = [doc.rootElement elementsForName:@"video"];
            for (GDataXMLElement *ele in elements) {
                VideoModel *video = [[VideoModel alloc] init];
                video.name = [ele attributeForName:@"name"].stringValue;
                video.url = [ele attributeForName:@"url"].stringValue;
                video.image = [ele attributeForName:@"image"].stringValue;
                video.length = [ele attributeForName:@"length"].stringValue.integerValue;
                
                [self.videos addObject:video];
            }
        }];
    }
    

    相关文章

      网友评论

          本文标题:iOS网络编程

          本文链接:https://www.haomeiwen.com/subject/flbsxqtx.html