1.首先你需要用CocoaPods导入这个库:
pod'CocoaAsyncSocket'
2.而后我们新建一个DCSocketManager类来管理这个类的一些代理方法,并生成一个本类的单例:
@interfaceDCSocketManager() {
NSString*_serverHost;//IP或者域名
int_serverPort;//端口,https一般是443
GCDAsyncSocket *_asyncSocket;//一个全局的对象
}
@property(nonatomic,strong)NSMutableData*sendData;//最终拼接好的需要发送出去的数据
@property(nonatomic,copy)NSString*uriString;//具体请求哪个接口,比如https://xxx.xxxxx.com/verificationCode里的verificationCode
@property(nonatomic,strong)NSDictionary*paramters;//Body里面需要传递的参数
@property(nonatomic,copy) CompletionHandler completeHandler;//收到返回数据后的回调Block
@property(nonatomic,strong)NSMutableArray*dcNetArr;//网络请求参数的暂存数组,后面会用到
@end
3.用socket连接http接口的域名与端口:
[_asyncSocket connectToHost:_serverHost onPort:_serverPort error:nil];
4.组装要发送的报文NSData:
- (NSMutableData*)sendData {
NSMutableData*packetData = [[NSMutableDataalloc] init];
NSData*crlfData = [@"\r\n"dataUsingEncoding:NSUTF8StringEncoding];//回车换行是http协议中每个字段的分隔符
[packetData appendData:[[NSStringstringWithFormat:@"GET /%@ HTTP/1.1",self.uriString] dataUsingEncoding:NSUTF8StringEncoding]];//拼接的请求行
[packetData appendData:crlfData];//每个字段后面都要跟一个回车换行
[packetData appendData:[@"DCVer: 1"dataUsingEncoding:NSUTF8StringEncoding]];//拼接的请求头字段,这个键值对和服务器协商内容,一般不止一个
[packetData appendData:crlfData];
[packetData appendData:[@"DCAid: test"dataUsingEncoding:NSUTF8StringEncoding]];//拼接的请求头字段,这个键值对和服务器协商内容,一般不止一个
[packetData appendData:crlfData];
[packetData appendData:[@"Content-Type: application/json; charset=utf-8"dataUsingEncoding:NSUTF8StringEncoding]];//发送数据的格式
[packetData appendData:crlfData];
[packetData appendData:[@"User-Agent: GCDAsyncSocket8.0"dataUsingEncoding:NSUTF8StringEncoding]];//代理类型,用来识别用户的操作系统及版本等信息,这里我随便填的,一般情况没什么用
[packetData appendData:crlfData];
[packetData appendData:[@"Host: xxx.xxxxxx.com"dataUsingEncoding:NSUTF8StringEncoding]];//IP或者域名
[packetData appendData:crlfData];
NSError*error;
NSData*bodyData = [NSJSONSerializationdataWithJSONObject:self.paramters options:0error:&error];
NSString*bodyString = [[NSStringalloc] initWithData:bodyData encoding:NSUTF8StringEncoding];//生成请求体的内容
[packetData appendData:[[NSStringstringWithFormat:@"Content-Length: %ld", bodyString.length] dataUsingEncoding:NSUTF8StringEncoding]];//说明请求体内容的长度
[packetData appendData:crlfData];
[packetData appendData:[@"Connection:close"dataUsingEncoding:NSUTF8StringEncoding]];
[packetData appendData:crlfData];
[packetData appendData:crlfData];//注意这里请求头拼接完成要加两个回车换行//以上http头信息就拼接完成,下面继续拼接上body信息
NSString*encodeBodyStr = [NSStringstringWithFormat:@"%@\r\n\r\n", bodyString];//请求体最后也要加上两个回车换行说明数据已经发送完毕
[packetData appendData:[encodeBodyStr dataUsingEncoding:NSUTF8StringEncoding]];
returnpacketData;
}
5.若想支持https接口,则需要加下面一个方法:
- (void)doTLSConnect:(GCDAsyncSocket *)sock {//HTTPS
NSMutableDictionary*sslSettings = [[NSMutableDictionaryalloc] init];
NSData*pkcs12data = [[NSDataalloc] initWithContentsOfFile:[[NSBundlemainBundle] pathForResource:@"xxx.xxxxxxx.com"ofType:@"p12"]];//已经支持https的网站会有CA证书,给服务器要一个导出的p12格式证书
CFDataRefinPKCS12Data = (CFDataRef)CFBridgingRetain(pkcs12data);
CFStringRefpassword =CFSTR("xxxxxx");//这里填写上面p12文件的密码
constvoid*keys[] = { kSecImportExportPassphrase };
constvoid*values[] = { password };
CFDictionaryRefoptions =CFDictionaryCreate(NULL, keys, values,1,NULL,NULL);
CFArrayRefitems =CFArrayCreate(NULL,0,0,NULL);
OSStatus securityError = SecPKCS12Import(inPKCS12Data, options, &items);
CFRelease(options);
CFRelease(password);
if(securityError == errSecSuccess) {
NSLog(@"Success opening p12 certificate.");
}
CFDictionaryRefidentityDict =CFArrayGetValueAtIndex(items,0);
SecIdentityRef myIdent = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
SecIdentityRef certArray[1] = { myIdent };
CFArrayRefmyCerts =CFArrayCreate(NULL, (void*)certArray,1,NULL);
[sslSettings setObject:(id)CFBridgingRelease(myCerts) forKey:(NSString*)kCFStreamSSLCertificates];
[sslSettings setObject:@"api.pandaworker.com"forKey:(NSString*)kCFStreamSSLPeerName]; [sock startTLS:sslSettings];//最后调用一下GCDAsyncSocket这个方法进行ssl设置就Ok了
}
6.至此用socket调用http接口的方法已经写完了,那么我们调用之后怎么获取返回数据呢,请往下看:
- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData*)data withTag:(long)tag
{//读取到返回数据时会调用
NSLog(@"didReadData length: %lu, tag: %ld", (unsignedlong)data.length, tag);
if(nil!=self.completeHandler) {
//如果请求成功,读取到服务器返回的data数据一般是一串字符串,需要根据返回数据格式做相应处理解析出来
NSString*string = [[NSStringalloc] initWithData:data encoding:NSUTF8StringEncoding];//
NSLog(@"%@", string);
NSRangestart = [string rangeOfString:@"{"];
NSRangeend = [string rangeOfString:@"}\r\n"];
NSString*sub;
if(end.location !=NSNotFound&& start.location !=NSNotFound) {
//如果返回的数据中不包含以上符号,会崩溃
sub = [string substringWithRange:NSMakeRange(start.location, end.location-start.location+1)];//这就是服务器返回的body体里的数据
NSData*subData = [sub dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary*subDic = [NSJSONSerializationJSONObjectWithData:subData options:0error:nil];
self.completeHandler(subDic);
}
}
[sock readDataWithTimeout:-1tag:0];
}