美文网首页
网络编程学习二

网络编程学习二

作者: coderhlt | 来源:发表于2018-08-02 20:07 被阅读26次

一、请求的数据格式

在网络数据传输过程中,服务器是不支持ios对象的,ios端是不能直接提交字符串、字典等,需要在提交前把数据转换为二进制数据。服务器在接收数据后需要对二进制数据进行解析,但服务器有必要知道这些数据格式是json,还是图片,还是音视频呢?这就需要客户端在请求头Content-Type中告知服务器。
在开发中一般请求的数据格式要么是表单,要么是json 。

  • 1.1 、x-www-form-urlencoded(表单)
    我们发送一个post请求时,默认数据就是以表单的形式提交的。
POST
header:
Content-Type: "x-www-form-urlencoded"
body:
key1=value1&key2=value2
/*key1=value1
key2=value2
*/
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:[NSURL URLWithString:@"http://apis.juhe.cn/catering/querybycity"]];
    request.HTTPMethod=@"POST";

   //设置请求数据类型
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

     NSData*requestdata=[@"key=9e0169318d2bdaa82abf75f3c0e7d173&city=上海"dataUsingEncoding:NSUTF8StringEncoding];
    request.HTTPBody=requestdata;
    NSURLSession *session=[NSURLSession sharedSession];
    NSURLSessionTask *sessiontask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

  }];
   [sessiontask resume];

1.2 、x-www-form-urlencoded(表单)

header:
Content-Type: "x-www-form-urlencoded"
body:
key1=value1
key2={"key3":value3, "key4": value4}

注意这里还是一个表单,表单里面嵌套了一个JSON字符串

    NSURL *url =[NSURL URLWithString:@"http://49.4.5.233:9111/api/getService"];
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod=@"POST";
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    

    //转换为jsonstring
    NSDictionary *dic=@{
                        @"nmae":@"zhangsan",
                        @"jobnumber":@"001"
                        };
    
    NSData *jsondata=[NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
    NSString  *jsonstring=[[NSString alloc]initWithData:jsondata encoding:NSUTF8StringEncoding];

//josnstring拼接到表单里
    NSString *paramas=[NSString   stringWithFormat:@"key=9e0169318d2bdaa82abf75f3c0e7d173&message=%@",jsonstring];
   NSData*requestdata=[paramas  dataUsingEncoding:NSUTF8StringEncoding];
   request.HTTPBody=requestdata;
   NSURLSession *session=[NSURLSession sharedSession];
    NSURLSessionTask *sessiontask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

  }];
   [sessiontask resume];
  • 2、json
header:
Content-Type: "application/json"

body:
{
    "key1": value1,
    "key2": value2
}
    NSURL *url =[NSURL URLWithString:@"http://nweeeeeikeji.com/jinyunfuni/product/homeVideoRecommend"];
    NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];//设置请求数据类型
    NSDictionary *dic=@{
                        @"imageType":@"homebanner",
                        @"loginO":@"1"
                        };
    NSData *jsondata=[NSJSONSerialization dataWithJSONObject:dic options:NSJSONWritingPrettyPrinted error:nil];
    request.HTTPMethod=@"POST";
    request.HTTPBody=jsondata;
    NSURLSession *session =[NSURLSession sharedSession];
    
    NSURLSessionDataTask *sessiontask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {

    }];
    
    [sessiontask resume];
}

二、AFN设置请求数据格式

AFN内部实现

@implementation AFJSONRequestSerializer
[mutableRequest setValue:@"application/json" forHTTPHeaderField:@"Content-Type"]

@implementation AFHTTPRequestSerializer
[mutableRequest setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"]

通过以上可以知道,AFN设置请求数据格式可以方便的通过AFHTTPSessionManager的requestSerializer属性进行设置。

  • 1、x-www-form-urlencoded(表单)
 AFHTTPSessionManager *sessionmanger=[[AFHTTPSessionManager alloc]init];
   sessionmanger.requestSerializer=[AFHTTPRequestSerializer serializer];
  • 2、json
AFHTTPSessionManager *sessionmanger=[[AFHTTPSessionManager alloc]init];
    sessionmanger.requestSerializer=[AFJSONRequestSerializer serializer]

三、AFN使用报错探究

源码:

- (void)viewDidLoad {
    [super viewDidLoad];
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager POST:@"https://www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {  
       NSLog(@"%@",responseObject);
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"请求失败--%@",error);
    }];
}

运行之后:请求失败--Error Domain=com.alamofire.error.serialization.response Code=-1016 "Request failed: unacceptable content-type: text/html" 。

分析:报错原因就是响应不接受 text/html类型.也就是afn序列化时不支持 text/html类型,我们需要手动设置一下manager.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"text/html"].

修改后:

- (void)viewDidLoad {
    [super viewDidLoad];
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    //对于服务器返回数据,告诉afn在序列化时支持text/html类型
    manager.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"text/html",@"application/json", nil];
    
    [manager POST:@"https://www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        NSLog(@"%@",responseObject);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"请求失败--%@",error);
    }];
}

运行之后: 请求失败--Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}

分析:对于服务器返回的数据,afn默认会把它当作json来处理。很显然,我们请求的百度首页 返回的并不是一个json文本,而是一个html网页,但是AFNetworking并不知道,它坚信请求的结果就是一个json文本!然后固执地以json的形式去解析,显然没办法把一个网页解析成一个字典或者数组,所以产生了上述错误.因此,我们需要手动设置 manager.responseSerializer=[AFHTTPResponseSerializer serializer]告诉afn以二进制的形式对它进行解析就好了。

纠正后:

- (void)viewDidLoad {
    [super viewDidLoad];
    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    
    //对于服务器返回数据,告诉afn在序列化时支持text/html类型
    manager.responseSerializer.acceptableContentTypes=[NSSet setWithObjects:@"text/html",@"application/json", nil];
    
    //对于服务器返回数据,以二进制的形式进行解析(如果返回的数据既不是xml也不是json那么应该修改成这样)
    manager.responseSerializer=[AFHTTPResponseSerializer serializer];
    
    [manager POST:@"https://www.baidu.com" parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        NSLog(@"%@",responseObject);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"请求失败--%@",error);
    }];
}

四、图片上传

multipart/form-data 用于文件上传领域,在iOS开发中很多时候需要会涉及到上传图片等服务器交互的操作,基本上全部都会使用Multipart/form-data的请求方式来完成上传.需要我们去严格按照规范的格式来组装请求体 , 每一个换行每一个空格都是不可忽略的 ,AFN已经很好的为我们封装了。

    AFHTTPSessionManager *manger = [AFHTTPSessionManager manager];
    [manger POST:@"http://120.25.226.186:32812/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
        NSData *data=[NSData dataWithContentsOfFile:@"/Users/reitaketachibana/Desktop/屏幕快照 2018-03-27 下午3.38.04.png"];
        [formData appendPartWithFileData:data name:@"file1" fileName:@"屏幕快照 2018-03-27 下午3.38.04.png"
                               mimeType:@"image/png"];
        
    } progress:^(NSProgress * _Nonnull uploadProgress) {
      NSLog(@"上传进度");
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        NSLog(@"上传成功%@",task.currentRequest.allHTTPHeaderFields);
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        NSLog(@"上传失败");
    }];

相关文章

  • 网络编程学习二

    一、请求的数据格式 在网络数据传输过程中,服务器是不支持ios对象的,ios端是不能直接提交字符串、字典等,需要在...

  • 网络编程学习二

    一、请求的数据格式 在网络数据传输过程中,服务器是不支持ios对象的,ios端是不能直接提交字符串、字典等,需要在...

  • Qt学习之网络编程(二)

    UDP协议 UDP协议(用户数据报协议)是一种简单轻量级、不可靠、面向数据报、无连接的传输层协议。之后我们会介绍T...

  • 网络基本了解

    网络基础 问题:为什么要学习网络编程?(1)网络编程是一种实时更新应用数据的常用手段(2)网络编程是开发优秀网络应...

  • 网络编程(二)

    Apache的HttpClient和Java的HttpURLConnection: 自己封装的网络请求类,第三方的...

  • 网络编程二

    网络编程二 一、AFNetworking第三方网络框架 AFNetworking2.0使用简单,对最新的iOS特性...

  • Android网络编程(八)源码解析OkHttp中篇[复用连接池

    相关文章 Android网络编程(一)HTTP协议原理Android网络编程(二)HttpClient与HttpU...

  • Android网络编程(九)Retrofit2前篇[基本使用]

    相关文章 Android网络编程(一)HTTP协议原理Android网络编程(二)HttpClient与HttpU...

  • socket通讯编程

    这一块属于网络编程,主要是学习TCP/IP四层的网络体系结构,学习TCP编程和UDP编程。 java.net中 一...

  • java网络编程实现QQ发消息文件,图片等内容

    前言:昨天我们已经初步学习了网络编程到底是怎么一回事儿,今天在此基础上继续学习网络编程,利用网络编程实现 QQ上...

网友评论

      本文标题:网络编程学习二

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