CocoaAsyncSocket實現局域網內通訊

內容概要

利用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

Socket1.gif

其餘

應爲NAT的存在,因此這裏只實現了在局域網下的通信,若想實現真正的想微信那樣的通信, 還須要本身再路由器下映射的端口號,實現內網穿透, 此外 還有不少細節須要實現~~ 路漫漫其修遠兮~~接口

相關文章
相關標籤/搜索