bob*_*off 5 network-programming objective-c nsstream ios multipeer-connectivity
我正在使用MPCF创建一个多人游戏.您可以使用iPhone控制iPad上的太空飞船.
我正在经历各种滞后和延迟以及随机时间和间隔的缓冲/暂停,现在已经登陆Apples Technical Q&A NW26论文,讨论禁用Nagle算法.我尝试了,但我的程序不断崩溃,我不明白为什么.似乎CFWriteStreamCopyProperty总是返回NULL.
- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
switch (eventCode) {
case NSStreamEventOpenCompleted:
// Trying to get a handle to the native socket
CFSocketNativeHandle rawsock;
// This always return NULL
CFDataRef socketData = CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)(stream), kCFStreamPropertySocketNativeHandle);
// And this row always crash (coz of socketData being NULL i guess)
CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&rawsock);
CFRelease(socketData);
// Code example from Apple that need a handle to the native socket, that I am trying to get above
int err;
static const int kOne = 1;
err = setsockopt(rawsock, IPPROTO_TCP, TCP_NODELAY, &kOne, sizeof(kOne));
if (err < 0) {
err = errno;
}
break;
default:
break;
}
}
Run Code Online (Sandbox Code Playgroud)
任何帮助表示赞赏.
你假设那stream是一个NSOutputStream,但也可以通过NSInputStream.所以它在那条线上崩溃了.
下面是一个示例代码,可以处理这两种情况并修复崩溃:
- (void)disableNaglesAlgorithmForStream:(NSStream *)stream {
CFDataRef socketData;
// Get socket data
if ([stream isKindOfClass:[NSOutputStream class]]) {
socketData = CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)((NSOutputStream *)stream), kCFStreamPropertySocketNativeHandle);
} else if ([stream isKindOfClass:[NSInputStream class]]) {
socketData = CFReadStreamCopyProperty((__bridge CFReadStreamRef)((NSInputStream *)stream), kCFStreamPropertySocketNativeHandle);
}
// get a handle to the native socket
CFSocketNativeHandle rawsock;
CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&rawsock);
CFRelease(socketData);
// Disable Nagle's algorythm
// Debug info
BOOL isInput = [stream isKindOfClass:[NSInputStream class]];
NSString * streamType = isInput ? @"INPUT" : @"OUTPUT";
int err;
static const int kOne = 1;
err = setsockopt(rawsock, IPPROTO_TCP, TCP_NODELAY, &kOne, sizeof(kOne));
if (err < 0) {
err = errno;
NSLog(@"Could Not Disable Nagle for %@ stream", streamType);
} else {
NSLog(@"Nagle Is Disabled for %@ stream", streamType);
}
}
Run Code Online (Sandbox Code Playgroud)
这应该在中调用 case NSStreamEventOpenCompleted:
对于任何想知道为什么它在复制粘贴时不能编译的人:
#import <arpa/inet.h> // for IPPROTO_TCP
#include <netinet/tcp.h> // for TCP_NODELAY
Run Code Online (Sandbox Code Playgroud)
但是,它对周期性延迟问题没有帮助. 我还在寻找一种方法来防止这种情况发生.
我录一个简单的视频,演示了这个问题,我相信你也遇到了同样一个: https://www.dropbox.com/s/omdqkbckph4b1y2/Multipeer%20Connectivity.mov?dl=0
编辑:我能够找到一种方法来解决周期性延迟问题.这是MCNearbyServiceAdvertiser导致问题的原因.您需要停止通告对等方以摆脱滞后:在连接成功后立即调用stopAdvertisingPeer您的MCNearbyServiceAdvertiser实例上的方法.
MCNearbyServiceAdvertiser *nearbyServiceAdvertiser;
- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state {
switch (state) {
case MCSessionStateConnected: {
dispatch_async(dispatch_get_main_queue(), ^{
[self.nearbyServiceAdvertiser stopAdvertisingPeer];
});
...
}
...
}
Run Code Online (Sandbox Code Playgroud)
但是延迟将在30秒后关闭.我不知道如何让它立刻消失.
| 归档时间: |
|
| 查看次数: |
1127 次 |
| 最近记录: |