CS193P第十七堂课摘要及心得笔记

2020-06-06 作者: 围观:110 19 评论

本系列课程即将迈入最后的尾声,而在这倒数第三堂课中,我们将学习到如何使用 Apple 的 Bonjour 来传递网路服务,以及透过 NSStream 来在网路上进行资料传输,此外还有 iPhone OS 3.0 中所新加入的 GameKit 套件,就让我们一起来看看吧!

Bonjour

Bonjour 是 Apple 在 2002 年所推出的一种网路服务搜索的协定,除了 Mac 和 iPhone 有支援以外,许多网路设备,像是支援网路列印的印表机也都使用 Bonjour 协定。

为了能够让读者了解 Bonjour 的概念,我们做一个简单的举例:假设我们想传送要列印的资料给网路上的印表机,首先必须得先设定印表机的 IP 地址以及其使用的 Port 等等资料,我们的电脑才能将资料传递过去。然而,透过支援 Bonjour 服务的印表机,我们就不需要自己手动设定这些 IP 地址等资讯,因为当印表机连上网路的同时,便会自动通知网路上其他支援 Bonjour 的设备,并且传递相关的设定资料。

很容易搞混的一点是,Bonjour 只有负责网路服务的寻找,并不负责底层的功能实做,这点需要注意。

在 Bonjour 协定下,每一个装置都会有自己的代号,这个代号最后的 Domain 通常是以.local. 代表本地的网路,像是 iPhone3GS.local.。而装置所提供的服务,也有不同的表示方式,如下图所示:

CS193P第十七堂课摘要及心得笔记

实际的运用上,NSStream 会透过呼叫 delegate 方法来表示他目前的状态,但要注意的是,读取跟写入仍然是同步执行的,也就是必须另外建立执行绪,否则程式就会卡在网路的传递上。

而诚如刚刚所提到的,在我们解析完 NSNetService 之后,可以直接呼叫以下方法取得输入跟输出的 NSStream:

NSInputStream *inputStream = nil; NSOutputStream *outputStream = nil; [netService getInputStream:&inputStream outputStream:&outputStream];

在取得 NSStream 之后,我们必须先开启它,才能进行读取或写入,而使用完毕之后,也必须关闭,程式码如下:

// 开启 [stream setDelegate:self]; [stream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [stream open];// 关闭 [stream close]; [stream removeFromRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes]; [stream setDelegate:nil];

这边可能大家有发现到,有个 NSRunLoop 的物件出现在呼叫方法中,什幺是 Run Loop 呢?在我们启动 iPhone 应用程式之后,便会一直在 Run Loop 里面等待事件的发生,像是触控事件或是硬体开关的切换等等。而为了能够让我们传输网路资料,我们必须将 NSStream 物件加入到 Run Loop 上才行。

CS193P第十七堂课摘要及心得笔记

而如前面所提及的,我们可以透过 NSStream 的 delegate 方法来确定状况,如下:

- stream:theStream handleEvent:streamEvent

而对于已经开启过的 NSOutputStream 我们就可以呼叫 - write:buffer maxLength:length 来进行资料的传递,该方法会回传成功传送出的资料长度,如下列範例:

const char *buff= “Hello World!”; NSUInteger buffLen = strlen; NSInteger writtenLength = [outputStream write:buff maxLength:strlen]; if{   [NSException raise:@”WriteFailure” format:@””]; }

读取 NSInputStream 的方法也很类似,透过呼叫 - read:buffer maxLength:length:

unit8_t buff[1024]; bzero); NSInteger readLength = [inputStream read:buff maxLength:sizeof - 1]; buff[readLength] = ‘\0’; NSLogbuff);GameKit

而在 iPhone OS 3.0 之后便加入了 GameKit 这个 framework,而这个 framework 可以帮助我们透过 Wi-Fi 或是蓝牙让使用者进行配对、建立连线,此外,也有提供音讯聊天的功能。在 GameKit 中提供了以下的类别:

GKSession 物件是整个 GameKit 的操作核心,我们可以用下列方法建立 GKSession 物件:

- initWithSessionID:sessionID displayName:name sessionMode:mode

而 GKSession 物件则包含了以下属性:

然而,单纯建立好 GKSession 并没有帮我们完成使用者之间的配对,必须另外透过 GKPeerPickerController,GKPeerPickerController 而提供了两种方法让使用者配对,分别是"nearby" 和"online",前者透过蓝牙进行配对,iPhone OS 会玩成大部份的工作,后者则是要让开发者自行建立网路主机,让使用者可以线上与全球使用者进行配对。

而使用上就如同其他 PickerController 一样,设定好 delegate 并将 view 加入到画面上后,物件就会接手处理,并且透过 delegate 方法建立 GKSession:

// 基本设定 GKPeerPickerController *peerPicker; peerPicker = [[GKPeerPickerController alloc] init]; peerPicker.delegate = self;// 选择连线模式 peerPicker.connectionMask = GKPeerPickerConnectionTypeOnline | GKPeerPickerConnectionTypeNearby;// 显示 alert [peerPicker show];

而当我们取得建立、配对完成的 GKSession 后,就可以简单的透过以下方法传送、读取资料了:

// 传送资料给特定对象 - sendData:data toPeers:peers withDataMode:mode error:error; // 传送资料给全部人 - sendDataToAllPeers:data withDataMode: mode error:error; // delegate 方法,接收资料 - receiveData:data fromPeer:peer inSession:session context:context;

若有不清楚的地方,可以参考课堂影片中的範例教学,里面有详细的操作示範以及範例程式。

结论

这一次的课程中,我们学到如何让使用者之间能够进行网路连线的互动,并且使用 GameKit 来简化整个操作流程。在下一次的课程中,我们将看到如何在 iPhone 上进行 Unit Testing 以及如何建立多国语系支援的应用程式,敬请期待!

参考资源
相关浏览推荐