因为需要实现自己的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(@"\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; }