python服務器:連接: https://pan.baidu.com/s/1hsd3ZYO 密碼: gyxgpython
其中已包含了下文須要安裝的 zope.interface 和 twisted 兩個文件,免去了你再去官網下載。數據庫
ps:該源碼只能在python2運行環境成功執行,python3雖然能鏈接可是沒法發送數據。數組
查看python版本方法,直接在命令行輸入python服務器
1.打開終端,用cd 命令進到chatserver.py這個文件所在的路勁。 oop
2.輸入python chatserver.py ui
若是報了這個沒有twisted這個錯誤的話,那就要安裝一下了。spa
下載地址:https://pypi.python.org/pypi/zope.interface (上面已提供,不用下載了)命令行
下載後你會獲得一個的壓縮包,代理
解壓後的文件目錄爲:code
而後在終端先進入這個名爲zope.interface-4.1.3的文件夾路徑,而後輸入sudo python setup.py install 接着要求輸入一下電腦密碼,即可以安裝zope.interface。
下載地址:https://twistedmatrix.com/trac/wiki/Downloads (上面已提供,不用下載了)
解壓後目錄:
安裝方法和上面同樣,sudo python setup.py install 接着輸入一下電腦密碼,即可以安裝twisted。
①先輸入python 回車
②輸入import twisted 回車 沒有任何提示,說明twisted安裝成功了
啓動成功啦。
1.搭建簡易UI
2.編寫 鏈接服務器 的BarButtonItem 方法:
//1.鏈接服務器 - (IBAction)connect:(id)sender { //創建鏈接 NSString *host = @"127.0.0.1"; int port = 12345; //定義輸入輸出流 CFReadStreamRef readStream; CFWriteStreamRef writeStream; CFStreamCreatePairWithSocketToHost(NULL, (__bridge CFStringRef)host, port, &readStream, &writeStream); //把C語言的輸入輸出流轉化成OC對象 _inputStream = (__bridge NSInputStream *)(readStream); _outputStream = (__bridge NSOutputStream *)(writeStream); //設置代理 監聽鏈接成功狀況 _inputStream.delegate = self; _outputStream.delegate = self; //把輸入輸出流添加到主運行循環(不添加主運行循環,代理可能不工做) [_inputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [_outputStream scheduleInRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; //打開輸入輸出流 [_inputStream open]; [_outputStream open]; }
3.編寫代理方法:(當上一步的 鏈接服務器 操做成功後,會走下面的代理方法,打印輸入輸出流打開完成 和 能夠發送字節, 該方法會在多種狀況下調用,具體看下面的枚舉說明)
//代理方法 -(void)stream:(NSStream *)aStream handleEvent:(NSStreamEvent)eventCode{ NSLog(@"%@",aStream); /* NSStreamEventOpenCompleted = 1UL << 0, //輸入輸出流打開完成 NSStreamEventHasBytesAvailable = 1UL << 1, //服務器有返回字節 NSStreamEventHasSpaceAvailable = 1UL << 2, //能夠發送字節 NSStreamEventErrorOccurred = 1UL << 3, //鏈接出現錯誤 NSStreamEventEndEncountered = 1UL << 4 //鏈接結束 */ switch (eventCode) { case NSStreamEventOpenCompleted: NSLog(@"輸入輸出流打開完成"); break; case NSStreamEventHasBytesAvailable: NSLog(@"服務器有返回字節"); //讀取服務器返回的數據 [self readData]; break; case NSStreamEventHasSpaceAvailable: NSLog(@"能夠發送字節"); break; case NSStreamEventErrorOccurred: NSLog(@"鏈接出現錯誤"); break; case NSStreamEventEndEncountered: NSLog(@"鏈接結束"); //關閉輸入流 [_inputStream close]; [_outputStream class]; //從主運行循環移除 [_inputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; [_outputStream removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; break; default: break; } }
讀取數據庫返回的數據 方法
//讀取服務器返回的數據 -(void)readData{ //創建緩衝區,即:建立一個能夠放1024個字節 的字節數組 uint8_t buf[1024]; //返回時間裝的字節數 NSInteger len = [_inputStream read:buf maxLength:sizeof(buf)]; //把字節數組轉化成字符串 ,把len的長度的字符 放到buf中 NSData *data = [NSData dataWithBytes:buf length:len]; //從服務器接收到的數據 NSString *recStr = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; NSLog(@"%@",recStr); }
4.編寫登陸方法 (登陸方法中,咱們有作發送數據給服務器,一旦登陸成功了,服務器會給出響應數據的,所以會調用 第3步驟的代理方法,控制檯打印服務器有返回字節)
//2.登陸 (會發送用戶名給服務器) - (IBAction)login:(id)sender { //發送用戶名和密碼(我這裏只發了用戶名,沒有密碼) /* 服務器規定: 若是要登陸,發送的數據格式爲:"iam:zhangsan"; 若是要發送聊天消息,數據格式爲:"msg:did you have dinner"; */ //登陸指令 NSString *loginStr = @"iam:zhangsan"; //把NSString 轉成 NSdata NSData *data = [loginStr dataUsingEncoding:NSUTF8StringEncoding]; //第一個參數(nonnull const uint8_t *) :要求傳一個uint8 * 類型的參數,這或其實就是unsigned char * [_outputStream write:data.bytes maxLength:data.length]; }
5.編寫發送數據方法
//點擊鍵盤上的return 發送消息 -(BOOL)textFieldShouldReturn:(UITextField *)textField{ NSString *text = textField.text; NSLog(@"%@",text); //聊天消息 NSString *msgStr = [NSString stringWithFormat:@"msg:%@",text]; //把NSString 轉成 NSdata NSData *data = [msgStr dataUsingEncoding:NSUTF8StringEncoding]; //第一個參數(nonnull const uint8_t *) :要求傳一個uint8 * 類型的參數,這或其實就是unsigned char * [_outputStream write:data.bytes maxLength:data.length]; return YES; }
到此爲止就完成了用輸入輸出流寫了一個簡單的即時通信的例子。
演示:
1.點擊鏈接服務器按鈕:控制檯打印以下,能夠看到輸入輸出流分別打開,而且能夠發送字節
2.點擊登陸按鈕:控制檯打印以下,能夠看到服務器返回了zhangsan has joined
3.在TextField中輸入要發送的內容,而後點擊鍵盤上的return。 能夠看到命令行中出現了qwer,咱們客戶端的內容傳到了服務器了。