利用CocoaAsyncSocket實現局域網內 iOS設備間的簡單通信.bash
1,服務端,用於接受客戶端鏈接.
2,客戶端,向服務端發起鏈接
3,通信協議,兩端都遵照協議格式進行數據收發無誤
複製代碼
很是簡略的協議只爲實現簡單的文字通信功能微信
1,長度包: |內容包長度(8bit)|
2,內容爆: |消息類型(1bit)|傳輸內容(不定)|
複製代碼
1,建立GCDSocketsocket
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
//設置代理 和 代理隊列,代理方法將在代理隊列中執行
//其實也能夠爲其中的socket通信執行的隊列,可是,隊列需要爲串行隊列,保持數據成流
複製代碼
2, 開始鏈接post
///連接至指定ip
-(BOOL)connectToIP:(NSString*)ip{
NSError* err;
//此處端口號爲服務端監聽端口
[self.socket connectToHost:ip onPort:8866 error:&err];
NSLog(@"===%@===",err);
return YES;
}
-(void)socket:(GCDAsyncSocket *)sock didConnectToHost:(NSString *)host port:(uint16_t)port{
//開始讀取操做,由於爲阻塞式,會等待直至有數據返回,進行讀取
[self.socket readDataToLength:8 withTimeout:-1 tag:IMDataTag_Length];
NSLog(@"===服務端接受連接===");
}
複製代碼
3,寫入數據ui
//發送模型
-(void)writeStr:(id<IMModelProtocol>)model{
//將要發送的模型轉換爲原始數據
NSData* data = [model getSendData];
//發送數據長度包,表示後續內容包的長度
[self.socket writeData:[data subdataWithRange:NSMakeRange(0, 8)] withTimeout:-1 tag:0];
//發送內容包
[self.socket writeData:[data subdataWithRange:NSMakeRange(8, data.length-8)] withTimeout:-1 tag:0];
}
複製代碼
4,讀取數據spa
-(void)socket:(GCDAsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag{
switch (tag) {
case IMDataTag_Length: //得到長度
self.currentDataLength = [self.analy getDataTotalLength:data];
//獲取長度後,進行內容讀取
[self.socket readDataToLength:self.currentDataLength withTimeout:-1 tag:IMDataTag_Content];
break;
case IMDataTag_Content: //得到內容
{
//將原始數據轉換爲須要的模型(我講模型與Data轉化的方法爲了簡介提到了外面)
id<IMModelProtocol> model = [self.analy getIMDataModelWithTotalLength:self.currentDataLength andData:data];
[[NSNotificationCenter defaultCenter] postNotificationName:IMGetModelNoti object:model];
[self.socket readDataToLength:8 withTimeout:-1 tag:IMDataTag_Length];
}
break;
}
}
複製代碼
1,建立接口監聽的socket代理
//此socket用來監聽接口,是否有服務端連接
self.socket = [[GCDAsyncSocket alloc] initWithDelegate:self delegateQueue:dispatch_get_global_queue(0, 0)];
//監聽 8886接口
[self.socket acceptOnPort:8866 error:nil];
複製代碼
2,接受到客戶端連接請求code
//當接受到連接請求時 回調該代理方法
-(void)socket:(GCDAsyncSocket *)sock didAcceptNewSocket:(GCDAsyncSocket *)newSocket{
// newSocket是對客戶端連接的封裝,若想保持鏈接,則將newSocket持有
// 對客戶端的 斷開,讀取,寫入都是對newSocket進行的
self.clientSsocket = newSocket;
newSocket.delegate = self.clientDelegate;
[newSocket setDelegateQueue:dispatch_get_global_queue(0, 0)];
//直接開始讀取(由於爲阻塞式的)
[newSocket readDataToLength:8 withTimeout:-1 tag:IMDataTag_Length];
}
複製代碼
而後對newSocket的讀寫操做就和客戶端同樣了. 效果以下,一個是虛擬機,一個是真機cdn
應爲NAT的存在,因此這裏只實現了在局域網下的通信,若想實現真正的想微信那樣的通信, 還須要本身再路由器下映射的端口號,實現內網穿透, 此外 還有不少細節須要實現~~ 路漫漫其修遠兮~~接口