您好,登錄后才能下訂單哦!
客戶端我們使用iPhone應(yīng)用程序,畫(huà)面比較簡(jiǎn)單。點(diǎn)擊發(fā)送按鈕,給服務(wù)器發(fā)送一些字符串過(guò)去。點(diǎn)擊接收按鈕就會(huì)從服務(wù)器讀取一些字符串,并且顯示在畫(huà)面上。
有關(guān)客戶端應(yīng)用的UI部分不再介紹了,我們直接看代碼部分,Socket客戶端可以采用CFStream或NSStream實(shí)現(xiàn),CFStream 實(shí)現(xiàn)方式與服務(wù)器端基本一樣。為了給讀者介紹更多的知識(shí),本例我們采用NSStream實(shí)現(xiàn)。NSStream實(shí)現(xiàn)采用Objective-C語(yǔ)言,一些 面向?qū)ο蟮念?lèi)。
下面我們看看客戶端視圖控制器ViewController.h
- #import <CoreFoundation/CoreFoundation.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #define PORT 9000
- @interface ViewController : UIViewController<NSStreamDelegate>
- {
- int flag ; //操作標(biāo)志 0為發(fā)送 1為接收
- }
- @property (nonatomic, retain) NSInputStream *inputStream;
- @property (nonatomic, retain) NSOutputStream *outputStream;
- @property (weak, nonatomic) IBOutlet UILabel *message;
- - (IBAction)sendData:(id)sender;
- - (IBAction)receiveData:(id)sender;
- @end
定義屬性inputStream和outputStream,它們輸入流NSInputStream和輸出流NSOutputStream類(lèi)。它們與服務(wù)器CFStream實(shí)現(xiàn)中的輸入流CFReadStreamRef和輸出流CFWriteStreamRef對(duì)應(yīng)的。
視圖控制器ViewController.m的初始化網(wǎng)絡(luò)方法initNetworkCommunication代碼:
- - (void)initNetworkCommunication
- {
- CFReadStreamRef readStream;
- CFWriteStreamRef writeStream;
- CFStreamCreatePairWithSocketToHost(NULL,
- (CFStringRef)@”192.168.1.103″, PORT, &readStream, &writeStream); ①
- _inputStream = (__bridge_transfer NSInputStream *)readStream; ②
- _outputStream = (__bridge_transfer NSOutputStream*)writeStream; ③
- [_inputStream setDelegate:self]; ④
- [_outputStream setDelegate:self]; ⑤
- [_inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
- forMode:NSDefaultRunLoopMode]; ⑥
- [_outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop]
- forMode:NSDefaultRunLoopMode]; ⑦
- [_inputStream open]; ⑧
- [_outputStream open]; ⑨
- }
點(diǎn)擊發(fā)送和接收按鈕觸發(fā)的方法如下:
- /* 點(diǎn)擊發(fā)送按鈕 */
- - (IBAction)sendData:(id)sender {
- flag = 0;
- [self initNetworkCommunication];
- }
- /* 點(diǎn)擊接收按鈕 */
- - (IBAction)receiveData:(id)sender {
- flag = 1;
- [self initNetworkCommunication];
- }
它們都調(diào)用initNetworkCommunication方法,并設(shè)置操作標(biāo)識(shí)flag,如果flag為0發(fā)送數(shù)據(jù),flag為1接收數(shù)據(jù)。
流的狀態(tài)的變化觸發(fā)很多事件,并回調(diào)NSStreamDelegate協(xié)議中定義的方法stream:handleEvent:,其代碼如下:
- -(void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
- NSString *event;
- switch (streamEvent) {
- case NSStreamEventNone:
- event = @”NSStreamEventNone”;
- break;
- case NSStreamEventOpenCompleted:
- event = @”NSStreamEventOpenCompleted”;
- break;
- case NSStreamEventHasBytesAvailable:
- event = @”NSStreamEventHasBytesAvailable”;
- if (flag ==1 && theStream == _inputStream) {
- NSMutableData *input = [[NSMutableData alloc] init];
- uint8_t buffer[1024]; ①
- int len;
- while([_inputStream hasBytesAvailable]) ②
- {
- len = [_inputStream read:buffer maxLength:sizeof(buffer)]; ③
- if (len > 0)
- {
- [input appendBytes:buffer length:len];
- }
- }
- NSString *resultstring = [[NSString alloc]
- initWithData:input encoding:NSUTF8StringEncoding];
- NSLog(@”接收:%@”,resultstring);
- _message.text = resultstring;
- }
- break;
- case NSStreamEventHasSpaceAvailable:
- event = @”NSStreamEventHasSpaceAvailable”;
- if (flag ==0 && theStream == _outputStream) {
- //輸出
- UInt8 buff[] = ”Hello Server!”; ④
- [_outputStream write:buff maxLength: strlen((const char*)buff)+1]; ⑤
- //關(guān)閉輸出流
- [_outputStream close];
- }
- break;
- case NSStreamEventErrorOccurred:
- event = @”NSStreamEventErrorOccurred”;
- [self close]; ⑥
- break;
- case NSStreamEventEndEncountered:
- event = @”NSStreamEventEndEncountered”;
- NSLog(@”Error:%d:%@”,[[theStream streamError] code],
- [[theStream streamError] localizedDescription]);
- break;
- default:
- [self close]; ⑦
- event = @”Unknown”;
- break;
- }
- NSLog(@”event——%@”,event);
- }
在讀取數(shù)據(jù)分支(NSStreamEventHasBytesAvailable)中,代碼第①行為讀取數(shù)據(jù)準(zhǔn)備緩沖區(qū),本例中設(shè)置的是1024個(gè)字節(jié),這個(gè)大小會(huì)對(duì)流的讀取有很多的影響。第②行代碼使用hasBytesAvailable方法判斷是否流有數(shù)據(jù)可以讀,如果有可讀數(shù)據(jù)就進(jìn)行循環(huán)讀取。第③行代碼使用流的read:maxLength:方法讀取數(shù)據(jù)到緩沖區(qū),第1個(gè)參數(shù)是緩沖區(qū)對(duì)象buffer,第2個(gè)參數(shù)是讀取的緩沖區(qū)的字節(jié)長(zhǎng)度。
在寫(xiě)入數(shù)據(jù)分支(NSStreamEventHasSpaceAvailable)中,代碼第④行是要寫(xiě)入的數(shù)據(jù),第⑤行代碼 [_outputStream write:buff maxLength: strlen((const char*)buff)+1]是寫(xiě)如數(shù)據(jù)方 法。
第⑥和第⑦行代碼[self close]調(diào)用close方法關(guān)閉,close方法代碼如下:
- -(void)close
- {
- [_outputStream close];
- [_outputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
- forMode:NSDefaultRunLoopMode];
- [_outputStream setDelegate:nil];
- [_inputStream close];
- [_inputStream removeFromRunLoop:[NSRunLoop currentRunLoop]
- forMode:NSDefaultRunLoopMode];
- [_inputStream setDelegate:nil];
- }
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。