最近在review并refactor項(xiàng)目組其他同事的代碼,其中涉及到一個(gè)知識(shí)點(diǎn):GCDAsyncSocket,socket異步通信,這是一個(gè)第三發(fā)開源框架,已經(jīng)被用的比較成熟了,如下是git倉庫地址:https://github.com/robbiehanson/CocoaAsyncSocket.git,有興趣的可以查看源碼,如果懶一點(diǎn)可以直接pod 'CocoaAsyncSocket' 到本地進(jìn)行使用
需求、
我們做的是人臉識(shí)別門禁考勤系統(tǒng),所以需要與閘機(jī)進(jìn)行通信;
實(shí)現(xiàn)思路:
門禁屬于一開一關(guān),以此視為一個(gè)生命周期,故采取socket短連接通信方式,用完之后client端主動(dòng)關(guān)閉socket連接,下次刷臉再次創(chuàng)建,重復(fù)這個(gè)過程;
為什么不采用長連接?
長連接需要保持心跳,過程繁雜,不夠干凈利索。而且占用資源,容易消耗電能,不可??;
上代碼:
//
-(void)setupSocket
{
if (_socket) {
[_socket setDelegate:nil];
_socket = nil;
}
_bReadFlag = NO;
_socket = [[AsyncSocket alloc] initWithDelegate:self];
NSLog(@"門禁IP:%@",[DefaultInfo shareUserInfo].strDoorSocket);
NSString *strDoorIP = [[[DefaultInfo shareUserInfo].strDoorSocket componentsSeparatedByString:@":"]firstObject];
int iDoorPort = [[[[DefaultInfo shareUserInfo].strDoorSocket componentsSeparatedByString:@":"]lastObject] intValue];
NSError *error = NULL;
BOOL bRet = [_socket connectToHost:strDoorIP
onPort:iDoorPort
error:&error];
if (bRet){
NSLog(@"門禁連接成功");
}else{
NSLog(@"門禁連接失敗:%@",error);
[_socket setDelegate:nil];
_socket = nil;
}
}
//代理方法
-(void)onSocketDidDisconnect:(AsyncSocket *)sock {
NSLog(@"門禁DidDisconnected.");
[_socket setDelegate:nil];
_socket = nil;
}
- (BOOL)onSocketWillConnect:(AsyncSocket *)sock {
NSLog(@"門禁onSocketWillConnect:");
return YES;
}
//詢問閘機(jī)server是否允許訪問
-(void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port {
NSLog(@"門禁Connected To %@:%i.", host, port);
[self sendHTTPRequestWith:@"AT\r\n"];
[self listenData];
}
//允許訪問,發(fā)送開門指令
-(void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSString *strReceived = [[NSString alloc] initWithBytes:[data bytes] length:[data length] encoding:NSUTF8StringEncoding];
if ([strReceived containsString:@"OK"] && !_bReadFlag) {
_bReadFlag = YES;
[self sendHTTPRequestWith:@"AT+STACH0=1,3\r\n"];
[self listenData];
}else {
//打開門之后生命周期結(jié)束,斷開連接
[_socket disconnect];
}
}