Disable Nagle#39;s algorithm for NSOutputStream(禁用 NSOutputStream 的 Nagle 算法)
问题描述
我正在使用 MPCF 创建多人游戏.您使用 iPhone 在 iPad 上控制宇宙飞船.
I am creating a multiplayer game using MPCF. You control a spacehip on the iPad using the iPhone.
我在随机时间和间隔遇到各种延迟和延迟以及缓冲/暂停,现在已经登陆 Apple 技术问答 NW26 论文讨论禁用 Nagle 算法.我尝试了一下,但我的程序不断崩溃,我不明白为什么.CFWriteStreamCopyProperty 似乎总是返回 NULL.
I am experiencing various amount of lag and latency and buffering/pauses at random times and intervals and have now landed on Apples Technical Q&A NW26 paper that talks about disabled the Nagle Algorithm. Im trying it out but my program keeps crashing and I dont understand why. It seem to be that CFWriteStreamCopyProperty always return 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;
}
}
感谢任何帮助.
推荐答案
你假设 stream
是一个 NSOutputStream
,但是有可能通过 NSInputStream代码>也.所以它在那条线上崩溃了.
You assuming that stream
is an NSOutputStream
, but there could be passed NSInputStream
also.
So it crashes on that line.
这是一个可以处理这两种情况并修复崩溃的示例代码:
Here is a sample code that can handle both scenarios and fixes a crash:
- (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);
}
}
这应该在 case NSStreamEventOpenCompleted:
对于任何想知道为什么复制粘贴时无法编译的人:
For anyone wondering why it does not compile when copy-pasted:
#import <arpa/inet.h> // for IPPROTO_TCP
#include <netinet/tcp.h> // for TCP_NODELAY
但是,它对周期性延迟问题没有帮助.我仍在寻找防止这种情况发生的方法.
However, it does NOT help with periodical latency issues. I'm still searching for a way to prevent that.
我录制了一个演示该问题的简单视频,我相信您也遇到了同样的问题:https://www.dropbox.com/s/omdqkbckph4b1y2/Multipeer%20Connectivity.mov?dl=0
I recorded a simple video that demonstrates the issue and I believe you are experiencing the same one: https://www.dropbox.com/s/omdqkbckph4b1y2/Multipeer%20Connectivity.mov?dl=0
我能够找到解决周期性延迟问题的方法.导致问题的是 MCNearbyServiceAdvertiser
.您需要停止为对等点做广告以消除滞后:连接成功后立即在您的 MCNearbyServiceAdvertiser
实例上调用 stopAdvertisingPeer
方法.
I was able to find a way to fix a periodical latency issues. It is an MCNearbyServiceAdvertiser
that causes the issues.
You need to stop advertising a peer in order to get rid of lags:
call a stopAdvertisingPeer
method on your MCNearbyServiceAdvertiser
instance right after the connection succeeded.
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];
});
...
}
...
}
但延迟只会在 30 秒后关闭.不知道怎么让它马上消失.
BUT the delays will turn off only after 30 seconds. I don't know how to make it disappear right away.
这篇关于禁用 NSOutputStream 的 Nagle 算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:禁用 NSOutputStream 的 Nagle 算法
基础教程推荐
- 当从同一个组件调用时,两个 IBAction 触发的顺序是什么? 2022-01-01
- 如何让对象对 Cocos2D 中的触摸做出反应? 2022-01-01
- android 应用程序已发布,但在 google play 中找不到 2022-01-01
- 如何在没有IB的情况下将2个按钮添加到右侧的UINavigationbar? 2022-01-01
- 如何在 UIImageView 中异步加载图像? 2022-01-01
- Kivy Buildozer 无法构建 apk,命令失败:./distribute.sh -m “kivy"d 2022-01-01
- 在 gmail 中为 ios 应用程序检索朋友的朋友 2022-01-01
- 如何在 iPhone 上显示来自 API 的 HTML 文本? 2022-01-01
- Android:对话框关闭而不调用关闭 2022-01-01
- UIWebView 委托方法 shouldStartLoadWithRequest:在 WKWebView 中等效? 2022-01-01