NSString asscii格式(2進制) 轉 utf8格式——解決iOS本身處理http socket數據,遇到Transfer-Encoding: chunked時

由於須要實現本身的http客戶端,就要本身模擬http 的socket通信;html

上行不難,本身處理好http便可。服務器

但下行時,服務器端的動態語言返回數據有可能會是這種格式:socket

http頭
16進製表示的數據長度1
數據1
16進製表示的數據長度2
數據2
……16進製表示的數據長度n
數據n
0
編碼

是這種格式時,返回頭信息裏面會有:code

Transfer-Encoding: chunked
htm

這麼一個頭;數據裏面表示每次發送的數據長度的16進制字符並非html的一部分,須要去掉,若是數據直接使用utf8編碼,那麼就會出問題:get

若是 數據1 裏面有中文,則「16進製表示的數據長度1」要比 數據1.length大,由於「16進製表示的數據長度1」是取的2進制長度,但「數據1.length」是以utf8編碼來算的string


因此不能默認使用utf8編碼,得這樣:it

-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
{
    NSString *newMessage = [[NSString alloc] initWithData:data encoding:NSISOLatin1StringEncoding];
    
    NSLog(@"\r\n=================HTTP RESPONSE START=================\r\nData get length: %lu,\r\n%@\r\n=================HTTP RESPONSE END=================\r\n ", (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:@"\r\n\r\n"];
            int len = range.length+range.location;
            dataGot =[dataGot substringFromIndex:len];
            
            NSString* rs = @"";
            NSString* lenStr;
            
            //NSLog(@"data len=%d---\n%@\n", dataGot.length,dataGot);
            
            while(YES){
                range = [dataGot rangeOfString:@"\r\n"];
                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;
}
相關文章
相關標籤/搜索