由於須要實現本身的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; }
- (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; }