OC中的socket通信


現在很多客戶端和服務器之間的交互都是通過JSON或者XML進行的,但是有時候如果數據量較小,JSON和XML就顯得比較冗余

•Socket允許使用長連接,允許應用程序運行在異步模式(提高效率),只有在需要的時候才接收數據
 
•在iOS中以NSStream(流)來發送和接收數據
•可以設置流的代理,對流狀態的變化做出相應
–連接建立
–接收到數據
–連接關閉
1.NSStream:數據流的父類,用於定義抽象特性,例如:打開、關閉代理,NSStream繼承自CFStream(Core Foundation)
2.NSInputStream:NSStream的子類,用於讀取輸入
3.NSOutputStream:NSSTream的子類,用於寫輸出
 
下面是開發步驟:
1.網絡連接設置
  1).設置網絡連接,綁定到主機和端口
  2).設置輸入流和輸出流的代理,監聽數據流的狀態
  3).將輸入輸出流添加至運行循環
  4).打開輸入流和輸出流
2.發送消息給服務器
3.有可讀取字節時,讀取服務器返回的內容
4.到達流末尾時,關閉流,同時並從主運行循環中刪除
 
 
廢話不多說,下面我們來嘗試使用以下Socket通信
首先定義輸入流和輸出流(PS.做過java開發的應該對輸入輸出流不陌生吧)
// 輸入流,用來讀取服務器返回的字節
NSInputStream *inputStream;
// 輸出流,用於給服務器發送字節
NSOutputStream *outputStream;

 

在OC中使用Socket需要用到CoreFoundation的一些流技術,創建流的時候需要用CFXXX等創建,然后在轉換為NSXXX

下面是跟服務器建建立鏈接的方法

// 建立與服務器的連接
-(void)connectToServer:(NSString *)host port:(NSInteger)port{
    
    // 創建CF下的讀入流
    CFReadStreamRef readStream;
    // 創建CF下的寫出流
    CFWriteStreamRef writeStream;
    
    // 創建流
    CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)(host), port, &readStream, &writeStream);
    
    // 將CFXXX流和NSXXX流建立對應關系
    inputStream = (__bridge NSInputStream *)(readStream);
    outputStream = (__bridge NSOutputStream *)(writeStream);
    
    // 設置通信過程中的代理
    inputStream.delegate = self;
    outputStream.delegate = self;
    
    // 將流對象添加到主運行循環(如果不加到主循環,Socket流是不會工作的)
    [inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    [outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    
    // 打開流
    [inputStream open];
    [outputStream open];
}

 

然后讓你的類遵守NSStreamDelegate協議

並且實現下面的方法進行監聽
-(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{
    NSLog(@"%u",eventCode);
    
    switch (eventCode) {
        case NSStreamEventOpenCompleted:
            NSLog(@"連接完成");
            break;
        case NSStreamEventHasBytesAvailable:
        {NSLog(@"有刻度字節");
            uint8_t buffer[10];
            NSMutableString *mstr = [NSMutableString string];
            int len;// = [inputStream read:buffer maxLength:sizeof(buffer)];
            do{
                len =  [inputStream read:buffer maxLength:sizeof(buffer)];
                NSString *s = [[NSString alloc] initWithBytes:buffer length:len encoding:NSUTF8StringEncoding];
                [mstr appendString:s];
            }while (len == sizeof(buffer));
           
            NSLog(@"====%@====",mstr);
        }
            break;
        case NSStreamEventHasSpaceAvailable:
            NSLog(@"可以寫入數據");
            break;
        case NSStreamEventErrorOccurred:
            NSLog(@"發生錯誤");
            break;
        case NSStreamEventEndEncountered:
            NSLog(@"流結束");
            // 做善后工作
            // 關閉流的同時,將流從主運行循環中刪除
            [aStream close];
            [aStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
        default:
            break;
    }
    
}

調用connect方法后控制台就會打印出連接完成,可以寫入數據,此時就可以寫入數據了,下面是寫入數據的代碼

 NSString *str = @"iam:kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk12345";
    NSData *data = [str dataUsingEncoding:NSUTF8StringEncoding];
    [outputStream write:data.bytes maxLength:data.length];
    

因為Socket傳輸的都是二進制流,所以當傳輸字符串時需要通過NSData轉為二進制數據

此外要記得流關閉的時候要從主循環中移除

 

一般我們開發的時候不會用原生的socket,一般都是用第三方的框架,這樣可以提高開發效率,減少開發過程中出現錯誤

 如果使用的是TCP協議一般用AsyncUdpSocket如果使用的是UPD一般使用asyncUdpSockey

http://pan.baidu.com/s/1gdDuGIf

上面的地址中有我的demo和一個python寫的服務腳本,,只需要在你的終端里面輸入 python+空格+那個py文件就運行起來了.這個文件運行起來以后你的電腦就是一台服務器了,,連接服務器的代碼里面host傳127.0.0.1   port傳12345就可以建立連接了


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM