socket网络间通信初识
NSOperation:
1. 指定同一時間最大執(zhí)行的操作數(shù)
queue.max……
2. 設(shè)定隊列中的任務(wù)時間的依賴關(guān)系
task1 依賴于 task2: task2 —> task1
3. 回到主線程(找到如何獲取主隊列的方式)[NSOperation mainQueue]:
keyword: iOS main queue
Socket: 網(wǎng)絡(luò)中的兩個程序通過雙向的通訊,達(dá)到交換數(shù)據(jù)的目的。
發(fā)送(客戶端):終端控制臺
接收(服務(wù)器端):? 終端控制臺(sever.py)
資源:網(wǎng)頁(www.sina.com.cn)/圖片/軟件/.......
1. 服務(wù)器監(jiān)聽狀態(tài) standby (開機(jī)+應(yīng)用程序啟動)
2. 客戶端發(fā)送請求Request給服務(wù)器端
3. 連接確認(rèn), 客戶端接收服務(wù)器返回的數(shù)據(jù)
客戶端:iOS應(yīng)用程序
服務(wù)器端:啟動server.py
#coding:utf-8from twisted.internet.protocol import Factory, Protocol from twisted.internet import reactorclass IphoneChat(Protocol):def connectionMade(self):self.factory.clients.append(self)print "當(dāng)前連線的客戶端有", self.factory.clientsdef connectionLost(self, reason):self.factory.clients.remove(self)def dataReceived(self, data):a = data.split(':')if len(a) > 1:command = a[0].strip()content = a[1].strip()msg = ""if command == "iam":self.name = contentmsg = self.name + " 加入了聊天室"elif command == "msg":msg = self.name + ": " + contentprint msgfor c in self.factory.clients:c.message(msg)def message(self, message):self.transport.write(message + '\n')factory = Factory() factory.clients = [] factory.protocol = IphoneChat reactor.listenTCP(1025, factory) print "Iphone Chat server started" reactor.run() 腳本代碼?
NSInputStream: ? ?讀取數(shù)據(jù)
NSOutputStream:寫數(shù)據(jù)
發(fā)送消息:
功能:
存放接收消息 —> NSArray —> UITableView
準(zhǔn)備工作:
UITableView準(zhǔn)備(datasource, delegate)
兩個stream的delegate (NSStreamDelegate)
具體實(shí)現(xiàn):
@interface ViewController () <UITableViewDataSource, UITableViewDelegate, NSStreamDelegate> @property (weak, nonatomic) IBOutlet UITableView *tableView; @property (weak, nonatomic) IBOutlet UITextField *messageTextField;//輸入流(讀) @property (nonatomic, strong) NSInputStream *inputStream;//輸出流(寫) @property (nonatomic, strong) NSOutputStream *outputStream;//存放服務(wù)器返回消息的可變數(shù)組 @property (nonatomic, strong) NSMutableArray *messageArray;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];//初始化可變數(shù)組對象self.messageArray = [NSMutableArray array];//設(shè)置delegateself.tableView.dataSource = self;self.tableView.delegate = self;//準(zhǔn)備工作:和服務(wù)器端進(jìn)行連接 [self createConnectionToServer];}- (void)createConnectionToServer {//telnet 196.112.122.11 1025//創(chuàng)建兩個stream相關(guān)的類 CFReadStreamRef readStream;CFWriteStreamRef writeStream;//NSStream不具有連接服務(wù)器的功能//創(chuàng)建和服務(wù)器的連接/**第二個參數(shù):連接服務(wù)器的ip地址 (localhost)第三個參數(shù):指定端口*/CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)@"localhost", 1025, &readStream, &writeStream);//將底層的CFStream轉(zhuǎn)換成NSStream相關(guān)的類self.inputStream = (__bridge NSInputStream *)readStream;self.outputStream = (__bridge NSOutputStream *)writeStream;//設(shè)置兩個stream的delegateself.inputStream.delegate = self;self.outputStream.delegate = self;//把這兩個stream添加到runloop中(原因:才可以響應(yīng)對應(yīng)的代理方法) [self.inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];[self.outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];//將兩個stream打開 [self.inputStream open];[self.outputStream open]; }- (IBAction)enterChatRoom:(id)sender {//iam:xxxxxNSString *text = @"iam:Maggie";//NSString --> NSDataNSData *data = [text dataUsingEncoding:NSUTF8StringEncoding];//寫數(shù)據(jù)(OutputSteam) [self.outputStream write:[data bytes] maxLength:[data length]]; }- (IBAction)sendMessage:(id)sender {//發(fā)送消息到服務(wù)器端(msg:xxxxx)NSString *messageStr = [NSString stringWithFormat:@"msg:%@", self.messageTextField.text];//往outputStream中寫數(shù)據(jù)NSData *data = [messageStr dataUsingEncoding:NSUTF8StringEncoding];[self.outputStream write:[data bytes] maxLength:[data length]];//清空textField文本self.messageTextField.text = nil; }#pragma mark -- NSStreamDelegate //針對兩個管道Stream, 處理不同的事件 - (void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode {switch (eventCode) {case NSStreamEventOpenCompleted:NSLog(@"Stream打開");break;case NSStreamEventHasSpaceAvailable:NSLog(@"Stream還有空間可以放數(shù)據(jù)");break;case NSStreamEventHasBytesAvailable:NSLog(@"此時Stream有數(shù)據(jù)");[self readBytes:aStream];break;case NSStreamEventErrorOccurred:NSLog(@"有錯誤出現(xiàn)");//把stream關(guān)掉 [self.inputStream close];[self.outputStream close];//從runloop中移除 [self.inputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];[self.outputStream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];break;default:break;}}- (void)readBytes:(NSStream *)aStream {//將數(shù)據(jù)顯示在table view上//首先判定是服務(wù)器返回的(將服務(wù)器消息顯示在table view上)if (aStream == self.inputStream) {unsigned char readData[1024];//讀取輸入流的數(shù)據(jù)(服務(wù)器返回來的數(shù)據(jù))while ([self.inputStream hasBytesAvailable]) {//獲取服務(wù)器返回的數(shù)據(jù)/**第一個參數(shù):讀取的數(shù)據(jù)存放對象第二個參數(shù):讀取的最大bytes數(shù)量*/NSInteger length = [self.inputStream read:readData maxLength:sizeof(readData)];if (length > 0) {//讀取到數(shù)據(jù)NSString *messageStr = [[NSString alloc] initWithBytes:readData length:length encoding:NSUTF8StringEncoding];//將獲取到的字符串添加到可變數(shù)組中 [self.messageArray addObject:messageStr];//顯示在table view上 [self.tableView reloadData];}}} }#pragma mark -- table view datasouce/delegate - (NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {return self.messageArray.count; }//設(shè)置cell - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {//創(chuàng)建identifierstatic NSString *cellID = @"messageCell";//從緩存池中獲取cell(Reuse可復(fù)用性)UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID];//如果緩存池中沒有,再重新創(chuàng)建if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellID];}//設(shè)置cell文本屬性cell.textLabel.text = self.messageArray[indexPath.row];return cell; }@end?
練習(xí):
1. 點(diǎn)中UITextFiled,鍵盤彈出,table view和其他控件上移
2. 讓table view最后一行,始終顯示用戶發(fā)送的最新的消息
官方socket實(shí)例代碼鏈接:
https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Conceptual/Streams/Articles/NetworkStreams.html#//apple_ref/doc/uid/20002277-BCIDFCDI
URL: (Uniform Resource Locator) 統(tǒng)?資源定位符
最完整格式:
協(xié)議://IP地址:端口/路徑/文件名字
一般格式:
IP地址(域名)/路徑/文件名字
協(xié)議的通俗說法:發(fā)送數(shù)據(jù)方和接收數(shù)據(jù)方規(guī)定的傳送數(shù)據(jù)的規(guī)則
File協(xié)議:從本地查找相應(yīng)的文件
URL —>
file:///Users/tarena/Downloads/testImages/aa.jpg
HTTP協(xié)議內(nèi)部數(shù)據(jù)
小例子:
把本地mac機(jī)器改裝成提供web服務(wù)(Apache軟件)的服務(wù)器步驟:
1. 查看Apache軟件是否安裝
sudo apachectl -v
輸入mac系統(tǒng)的密碼
2. 啟動apache軟件
sudo apachectl start
3. 在瀏覽器中輸入localhost,顯示It works!就表示mac機(jī)器成為了可以提供網(wǎng)頁服務(wù)的機(jī)器
http://IP地址:端口/路徑/文件名字
MIME: 客戶端(瀏覽器)指定服務(wù)器返回的類型(xxx.html)
文本類型:
text/html:不僅包含文本,也包含.jpg/.gif/.....
text/xml
text/plain: 只能包含文本
http協(xié)議的規(guī)則:
1. 指定MIME類型: text/html
2. 方法:
??? a. GET (獲取資源:html文件)
??? b. DELETE (刪除資源:圖片)
??? c. POST: 登錄(用戶名/密碼)
??? d. PUT: 上傳文件/上傳信息
3. status code: 服務(wù)返回的狀態(tài)碼
???? a. 成功:200/OK
???? c. 失敗:
???? 404 -> 未找到資源(html文件)
???? 400 -> 客戶端的請求,服務(wù)器端無法解析
???? 501 -> 服務(wù)器錯誤
4.響應(yīng)Response (服務(wù)器返回):
content-length: 總長度多少
content-range (****): 默認(rèn)服務(wù)器會返回客戶端請求的資源的總數(shù)據(jù)
iOS中發(fā)送網(wǎng)絡(luò)請求的方案:
方案一:
NSURLConnection (相對麻煩/更加理解http原理):
方案二
NSURLSession (簡單/封裝性高):
?
此案例主要以方案一來實(shí)現(xiàn):
樣例:界面上輸入任意一個網(wǎng)址(URL), 將返回的網(wǎng)頁顯示到界面上(xxx.html) (NSURLConnection)
UI界面:UITextField; UIButton; UIWebView(內(nèi)嵌瀏覽器)
具體實(shí)現(xiàn):
@interface ViewController () @property (weak, nonatomic) IBOutlet UIWebView *webView; @property (weak, nonatomic) IBOutlet UITextField *urlTextField;//界面輸入的URL @property (nonatomic, strong) NSURL *url;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];} //發(fā)送請求Request ---> 接收響應(yīng)Response - (IBAction)sendSyncRequest:(id)sender {//NSURLConnection//1.創(chuàng)建一個客戶端發(fā)送請求對象self.url = [NSURL URLWithString:self.urlTextField.text];NSURLRequest *urlRequest = [NSURLRequest requestWithURL:self.url];//2.開始執(zhí)行發(fā)送的同步請求//3.獲取服務(wù)器返回的html文件NSError *error = nil;NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:nil error:&error];if (error) {NSLog(@"發(fā)送請求失敗:%@", error.userInfo);return;}//4.并顯示在UIWebView上 [self.webView loadData:dataMIMEType:@"text/html"textEncodingName:@"utf-8"baseURL:nil];NSLog(@"請求執(zhí)行完畢%@; 數(shù)據(jù)的大小%lu", [NSThread currentThread], (unsigned long)data.length); }- (IBAction)sendAsyncRequest:(id)sender {//1.創(chuàng)建客戶端發(fā)送請求對象self.url = [NSURL URLWithString:self.urlTextField.text];NSURLRequest *request = [NSURLRequest requestWithURL:self.url];//2.異步執(zhí)行請求//創(chuàng)建非主隊列NSOperationQueue *queue = [[NSOperationQueue alloc] init];[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {//獲取response的狀態(tài)碼(判定服務(wù)器是否返回成功200)//data:服務(wù)器返回的數(shù)據(jù)//connectionError:具體的錯誤NSLog(@"返回%@", [NSThread currentThread]);NSInteger retStatusCode = [(NSHTTPURLResponse *)response statusCode];if (retStatusCode == 200) {//回到主線程更新界面UIWebViewdispatch_async(dispatch_get_main_queue(), ^{//3.顯示服務(wù)器返回的數(shù)據(jù)到UIWebView[self.webView loadData:data MIMEType:@"text/html" textEncodingName:@"utf-8" baseURL:nil];});} else {NSLog(@"失敗%@",connectionError.userInfo);}}]; }@end?
轉(zhuǎn)載于:https://www.cnblogs.com/YKiOS/p/4802366.html
總結(jié)
以上是生活随笔為你收集整理的socket网络间通信初识的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: animation的6个属性
- 下一篇: 使界面里的组件更圆滑