• NSString asscii格式(2进制) 转 utf8格式——解决iOS自己处理http socket数据,遇到Transfer-Encoding: chunked时


    因为需要实现自己的http客户端,就要自己模拟http 的socket通讯;

    上行不难,自己处理好http即可。

    但下行时,服务器端的动态语言返回数据有可能会是这种格式:

    http头
    16进制表示的数据长度1
    数据1
    16进制表示的数据长度2
    数据2
    ……16进制表示的数据长度n
    数据n
    0

    是这种格式时,返回头信息里面会有:

    Transfer-Encoding: chunked

    这么一个头;数据里面表示每次发送的数据长度的16进制字符并不是html的一部分,需要去掉,如果数据直接使用utf8编码,那么就会出问题:

    如果 数据1 里面有中文,则“16进制表示的数据长度1”要比 数据1.length大,因为“16进制表示的数据长度1”是取的2进制长度,但“数据1.length”是以utf8编码来算的


    所以不能默认使用utf8编码,得这样:

    -(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
    {
        NSString *newMessage = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
        
        NSLog(@"
    =================HTTP RESPONSE START=================
    Data get length: %lu,
    %@
    =================HTTP RESPONSE END=================
     ", (unsigned long)data.length, newMessage);
        [sock readDataWithTimeout:-1 tag:0];
        if(httpStatus<3 && [newMessage rangeOfString:@"Transfer-Encoding: chunked"].length>0){
            isChunked = YES;
            httpStatus = 3 ;
        }
        
        dataGot = [dataGot stringByAppendingString:newMessage];
    
        httpStatus = 3;
    }

    最后处理去处长度字符,然后转换为utf8编码:

    - (void)socketDidDisconnect:(GCDAsyncSocket *)sock withError:(NSError *)err
    {
        NSLog(@"Disconnected %@", err);
        if(httpStatus<3)
            [delegate httpDataGot:@"" rs:NO];
        else{
            if(isChunked){
                NSRange range = [dataGot rangeOfString:@"
    
    "];
                int len = range.length+range.location;
                dataGot =[dataGot substringFromIndex:len];
                
                NSString* rs = @"";
                NSString* lenStr;
                
                //NSLog(@"data len=%d---
    %@
    ", dataGot.length,dataGot);
                
                while(YES){
                    range = [dataGot rangeOfString:@"
    "];
                    if(range.length==0)
                        break;
                    lenStr = [dataGot substringToIndex:range.location];
                    firstChunkedLen = strtoul([lenStr UTF8String], 0, 16);
                    if(firstChunkedLen==0)
                        break;
                    dataGot = [dataGot substringFromIndex:range.location+range.length];
                    rs = [rs stringByAppendingString:[dataGot substringToIndex:firstChunkedLen]];
                    dataGot = [dataGot substringFromIndex:firstChunkedLen];
                }
               /*
                 NSString *s1 = [NSString stringWithCString:[rs cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding];
               */
                
                [delegate httpDataGot:[NSString stringWithCString:[rs cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding] rs:YES];
            }
            else
                [delegate httpDataGot:[NSString stringWithCString:[dataGot cStringUsingEncoding:NSISOLatin1StringEncoding] encoding:NSUTF8StringEncoding] rs:YES];
        
        }
        isChunked = NO;
        httpStatus = 0;
    }


  • 相关阅读:
    JavaSE 基础 第54节 继承Thread类创建线程
    flask 项目部分业务逻辑
    js生成随机的uuid
    增量式爬虫
    分布式爬虫
    scrapy 的分页爬取 CrawlSpider
    scrapy 请求传参
    scrapy增加爬取效率
    scrapy框架
    模拟登陆request-session
  • 原文地址:https://www.cnblogs.com/lein317/p/5067553.html
Copyright © 2020-2023  润新知