Socket調(diào)用HTTP接口

1.首先你需要用CocoaPods導入這個庫:

pod'CocoaAsyncSocket'

2.而后我們新建一個DCSocketManager類來管理這個類的一些代理方法,并生成一個本類的單例:

@interfaceDCSocketManager() {

NSString*_serverHost;//IP或者域名

int_serverPort;//端口,https一般是443

GCDAsyncSocket *_asyncSocket;//一個全局的對象

}

@property(nonatomic,strong)NSMutableData*sendData;//最終拼接好的需要發(fā)送出去的數(shù)據(jù)

@property(nonatomic,copy)NSString*uriString;//具體請求哪個接口,比如https://xxx.xxxxx.com/verificationCode里的verificationCode

@property(nonatomic,strong)NSDictionary*paramters;//Body里面需要傳遞的參數(shù)

@property(nonatomic,copy) CompletionHandler completeHandler;//收到返回數(shù)據(jù)后的回調(diào)Block

@property(nonatomic,strong)NSMutableArray*dcNetArr;//網(wǎng)絡請求參數(shù)的暫存數(shù)組,后面會用到

@end


3.用socket連接http接口的域名與端口:

[_asyncSocket connectToHost:_serverHost onPort:_serverPort error:nil];

4.組裝要發(fā)送的報文NSData:

- (NSMutableData*)sendData {

NSMutableData*packetData = [[NSMutableDataalloc] init];

NSData*crlfData = [@"\r\n"dataUsingEncoding:NSUTF8StringEncoding];//回車換行是http協(xié)議中每個字段的分隔符

[packetData appendData:[[NSStringstringWithFormat:@"GET /%@ HTTP/1.1",self.uriString] dataUsingEncoding:NSUTF8StringEncoding]];//拼接的請求行

[packetData appendData:crlfData];//每個字段后面都要跟一個回車換行

[packetData appendData:[@"DCVer: 1"dataUsingEncoding:NSUTF8StringEncoding]];//拼接的請求頭字段,這個鍵值對和服務器協(xié)商內(nèi)容,一般不止一個

[packetData appendData:crlfData];

?[packetData appendData:[@"DCAid: test"dataUsingEncoding:NSUTF8StringEncoding]];//拼接的請求頭字段,這個鍵值對和服務器協(xié)商內(nèi)容,一般不止一個

[packetData appendData:crlfData];?

?[packetData appendData:[@"Content-Type: application/json; charset=utf-8"dataUsingEncoding:NSUTF8StringEncoding]];//發(fā)送數(shù)據(jù)的格式

[packetData appendData:crlfData];

?[packetData appendData:[@"User-Agent: GCDAsyncSocket8.0"dataUsingEncoding:NSUTF8StringEncoding]];//代理類型,用來識別用戶的操作系統(tǒng)及版本等信息,這里我隨便填的,一般情況沒什么用

[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];//生成請求體的內(nèi)容

[packetData appendData:[[NSStringstringWithFormat:@"Content-Length: %ld", bodyString.length] dataUsingEncoding:NSUTF8StringEncoding]];//說明請求體內(nèi)容的長度

[packetData appendData:crlfData];

?[packetData appendData:[@"Connection:close"dataUsingEncoding:NSUTF8StringEncoding]];

?[packetData appendData:crlfData];?

?[packetData appendData:crlfData];//注意這里請求頭拼接完成要加兩個回車換行//以上http頭信息就拼接完成,下面繼續(xù)拼接上body信息

NSString*encodeBodyStr = [NSStringstringWithFormat:@"%@\r\n\r\n", bodyString];//請求體最后也要加上兩個回車換行說明數(shù)據(jù)已經(jīng)發(fā)送完畢

[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"]];//已經(jīng)支持https的網(wǎng)站會有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];//最后調(diào)用一下GCDAsyncSocket這個方法進行ssl設置就Ok了

}

6.至此用socket調(diào)用http接口的方法已經(jīng)寫完了,那么我們調(diào)用之后怎么獲取返回數(shù)據(jù)呢,請往下看:

- (void)socket:(GCDAsyncSocket *)sock didReadData:(NSData*)data withTag:(long)tag

{//讀取到返回數(shù)據(jù)時會調(diào)用

NSLog(@"didReadData length: %lu, tag: %ld", (unsignedlong)data.length, tag);

if(nil!=self.completeHandler) {

//如果請求成功,讀取到服務器返回的data數(shù)據(jù)一般是一串字符串,需要根據(jù)返回數(shù)據(jù)格式做相應處理解析出來

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) {

//如果返回的數(shù)據(jù)中不包含以上符號,會崩潰

sub = [string substringWithRange:NSMakeRange(start.location, end.location-start.location+1)];//這就是服務器返回的body體里的數(shù)據(jù)

NSData*subData = [sub dataUsingEncoding:NSUTF8StringEncoding];

NSDictionary*subDic = [NSJSONSerializationJSONObjectWithData:subData options:0error:nil];

self.completeHandler(subDic);

?}?

?}

?[sock readDataWithTimeout:-1tag:0];

}

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容