現在很多客戶端和服務器之間的交互都是通過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就可以建立連接了