Reto:Swift实时协作的P2P框架。
sReto 2.0与Swift 3兼容!若要支持Swift 2,请使用旧版本,例如1.4.1。
注意:还有适用于Windows和Unix的Java版本jReto
Reto是一个可扩展的P2P网络框架,用Swift和Java 8实现,两种语言提供相同的API。
框架的最重要特性包括
Reto设计用于通过实现Reto "模块"轻松扩展以使用其他网络技术;默认情况下,它提供了两个模块
安装sReto的推荐方法是使用CocoaPods包管理器,因为它提供灵活的依赖关系管理。
sReto 2.0可以作为框架集成到iOS 9.0+和OS X 10.9+。尽管它是用Swift实现的,但它可以在Objective-C和Swift项目中使用。以下是使用CocoaPods包含Reto所需的步骤。
开始发现/广告
广告和发现由LocalPeer
类管理。LocalPeer
需要一个或多个Reto模块才能运行。在此示例中,我们将使用WlanModule
。
Swift
// 1. Create the WlanModule
let wlanModule = WlanModule(type: "ExampleType", dispatchQueue: DispatchQueue.main)
// 2. Create the LocalPeer
let localPeer = LocalPeer(modules: [wlanModule], dispatchQueue: DispatchQueue.main)
// 3. Starting the LocalPeer
localPeer.start(
onPeerDiscovered: { peer in print("Discovered peer: \(peer)") },
onPeerRemoved: { peer in print("Removed peer: \(peer)") },
onIncomingConnection: { peer, connection in print("Received incoming connection: \(connection) from peer: \(peer)"") },
displayName: "MyLocalPeer"
)
Objective-C
// 1. Create the WlanModule
WlanModule* wlanModule = [[WlanModule alloc] initWithType: "ExampleType" dispatchQueue: dispatch_get_main_queue()];
// 2. Create the LocalPeer
LocalPeer* localPeer = [[LocalPeer alloc] initWithModules: @[wlanModule] dispatchQueue: dispatch_get_main_queue())
// 3. Starting the LocalPeer
[localPeer startOnPeerDiscovered:^(RemotePeer *peer) {
NSLog(@"Found peer: %@", peer);
} onPeerRemoved:^(RemotePeer *peer) {
NSLog(@"Removed peer: %@", peer);
} onIncomingConnection:^(RemotePeer *peer, Connection *connection) {
NSLog(@"Received incoming connection: %@ from peer: %@", connection, peer);
} displayName: @"MyLocalPeer"];
使用同一类型参数的WlanModule的任何两个应用程序将在局域网中发现彼此。因此,您应选择一个独特的类型参数。
在Swift和Java中,将一个dispatch queue传递给LocalPeer;所有网络操作都使用此队列执行。此外,所有回调也在此队列上发生。
Java中也使用相同的原则;这里使用Executor代替了调度队列。所有回调都是通过这个Executor的线程进行分发的。
在很多情况下,使用主调度队列/在GUI线程上运行的Executor是可以的,因为Reto不会在队列上执行任何阻塞操作。但是,如果有很多数据正在发送和处理,将操作移动到后台线程可能是个好主意。
当启动LocalPeer
时,三个闭包作为参数传递。
onPeerDiscovered
闭包。onPeerRemoved
闭包。RemotePeer
与LocalPeer
建立连接时,都会调用onIncomingConnection
闭包。第一个闭包可以让你访问到RemotePeer
对象,这些对象可以用来与那些对等节点建立连接。
建立连接和发送数据
Swift
// 1. Establishing a connection
let connection = someRemotePeer.connect()
// 2. Registering a callback the onClose event
connection.onClose = { connection in print("Connection closed.") }
// 3. Receiving data
connection.onData = { data in print("Received data!") }
// 4. Sending data
connection.send(data: someData)
Objective-C
// 1. Establishing a connection
Connection *connection = [someRemotePeer connect];
// 2. Registering a callback the onClose event
connection.onClose = ^(Connection* connection) {
NSLog(@"Connection closed.");
};
// 3. Receiving data
connection.onData = ^(Connection* connection, NSData* data) {
NSLog(@"Received data!");
}
// 4. Sending data
[connection sendData: someData];
可以通过在RemotePeer
上简单调用connect
方法来建立连接。
这允许你注册一些用于不同事件的回调,例如,当连接关闭时被调用的onClose
。然而,这些回调大多是可选的,但如果你想通过连接接收数据,则必须设置onTransfer
或onData
回调。
在这个例子中,设置了onData
回调,当接收到数据时会被调用。对于更细粒度的数据传输控制,请使用onTransfer
回调。
数据传输
虽然上述技术可以用来发送数据,但你可能需要更多的信息。`Transfer`类提供了更多信息和工具。以下仅给出使用这些特性的简短示例;然而,`Transfer`类还提供了更多方法和功能。请检查类文档以了解更多信息。
Swift
// 1. Configuring a connection to receive transfers example
someConnection.onTransfer = {
connection, transfer in
// 2. Configuring a transfer to let you handle data as it is received, instead of letting the transfer buffer all data
transfer.onPartialData = { transfer, data in print("Received a chunk of data!") }
// 3. Registering for progress updates
transfer.onProgress = { transfer in print("Current progress: \(transfer.progress) of \(transfer.length)") }
}
// 4. Sending a transfer example with a data provider
let transfer = someConnection.send(dataLength: someData.length, dataProvider: { range in return someData })
// 5. Registering for progress updates
transfer.onProgress = { transfer in print("Current progress: \(transfer.progress) of \(transfer.length)") }
Objective-C
// 1. Configuring a connection to receive transfers example
connection.onTransfer = ^(Connection* connection, InTransfer* transfer) {
// 2. Configuring a transfer to let you handle data as it is received, instead of letting the transfer buffer all data
transfer.onPartialData = ^(Transfer* transfer, NSData* data) {
NSLog(@"Received a chunk of data!");
};
// 3. Registering for progress updates
transfer.onProgress = ^(Transfer* transfer) {
NSLog(@"Current progress: %li of %li", transfer.progress, (long)transfer.length);
};
};
// 4. Sending a transfer example with a data provider
Transfer* transfer = [connection sendWithDataLength: 1 dataProvider:^NSData *(NSRange range) {
return somehowProvideDataForRange(range);
}];
// 5. Registering for progress updates
transfer.onProgress = ^(Transfer* transfer) {
NSLog(@"Current progress: %li of %li", transfer.progress, transfer.length);
};