RoUTP 是一个简单的可靠-不可靠传输协议 (Reliable-over-Unreliable Transport Protocol) 的 Objective-C 实现。其首要目标是作为 Apple Game Center 中 “GKMatch GKMatchSendDataReliable 数据包丢失问题” 的一个绕过方案(见 Stack Overflow 问题 和 验证示例)。但一般来说,它也可以用于其他任何不可靠的协议。
RoUTP 作为您应用程序和不可靠传输之间的附加传输层。它将所有已发送的消息保存下来,直到每个接收到的消息得到确认,再次发送丢失的消息,并在出现序列错误时缓冲接收到的消息。技术上,发送者对所有发送的消息进行编号,接收者周期性地发送积极的 选择性确认。
以下是在两玩家 Game Center 游戏中使用 RoUTP 的示例。假设代码如下:
@interface MyController : UIViewController <GKMatchDelegate>
@property (nonatomic,strong) GKMatch *gkMatch;
@end
@implementation MyController
-(void)sendData:(NSData *)data{
NSError *error;
[self.gkMatch sendDataToAllPlayers:data
withDataMode:GKMatchSendDataReliable
error:&error];
// …
}
-(void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID{
[self doSomethingWithReceivedData:data];
}
@end
让我们添加 RoUTP
// 1. Import ROUSession.h header
#import "ROUSession.h"
@interface MyController : UIViewController <GKMatchDelegate,
ROUSessionDelegate> // 2. implement its delegate
@property (nonatomic,strong) GKMatch *gkMatch;
@property (nonatomic,strong) ROUSession *rouSession; // 3. add ROUSession property
@end
@implementation MyController
-(void)startGame{
// 4. Make a ROUSession instance and set its delegate
self.rouSession = [ROUSession new];
self.rouSession.delegate = self;
}
-(void)sendData:(NSData *)data{
// 5. Send data to ROUSession instead of GKMatch
[self.rouSession sendData:data];
}
-(void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID{
// 6. Send data from GKMatch to ROUSession
[self.rouSession receiveData:data];
}
-(void)session:(ROUSession *)session preparedDataForSending:(NSData *)data{
// 7. Send prepared data from ROUSession to GKMatch
NSError *error;
[self.gkMatch sendDataToAllPlayers:data
withDataMode:GKMatchSendDataUnreliable // we can use unreliable mode now
error:&error];
// …
}
-(void)session:(ROUSession *)session receivedData:(NSData *)data{
// 8. Process ready data from ROUSession
[self doSomethingWithReceivedData:data];
}
-(void)endGame{
// 9. Clean delegate and release session when it is no more needed.
self.rouSession.delegate = nil;
self.rouSession = nil;
}
@end
MIT 许可证。