gpt4 book ai didi

iphone - 如何在后台保持VOIP套接字连接?

转载 作者:行者123 更新时间:2023-12-03 18:19:53 25 4
gpt4 key购买 nike

我的应用程序要求:由于某些原因,我应该保持套接字连接以触发服务器推送上的本地通知,而不使用推送通知 (APN)。所以我使用iPhone的VOIP后台功能来维持套接字连接。

<强>1。我已经为 VOIP 配置了一个流,以便保持套接字连接在后台运行,那么我应该设置什么超时值?一旦超时,socket连接会终止吗?如何让我的应用程序始终监听套接字?

客户端流配置如下,

NSString *urlStr = @"http://192.168.0.108";
NSURL *website = [NSURL URLWithString:urlStr];
CFReadStreamRef readStream;
CFWriteStreamRef writeStream;
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 1234, &readStream, &writeStream);

CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);

NSInputStream *inputStream = (NSInputStream *)readStream;
NSOutputStream *outputStream = (NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
[outputStream setDelegate:self];
[outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];

<强>2。我应该在处理程序 applicationDidEnterBackground 中重新连接流吗:

   [[UIApplication sharedApplication] setKeepAliveTimeout:86400 handler:^(void) 
{

if (inputStream)
[inputStream close];
if (outputStream)
[outputStream close];


urlStr = @"http://192.168.0.108";
website = [NSURL URLWithString:urlStr];
CFStreamCreatePairWithSocketToHost(NULL, (CFStringRef)[website host], 1234, &readStream, &writeStream);
CFReadStreamSetProperty(readStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
CFWriteStreamSetProperty(writeStream, kCFStreamNetworkServiceType, kCFStreamNetworkServiceTypeVoIP);
inputStream = (NSInputStream *)readStream;
outputStream = (NSOutputStream *)writeStream;
[inputStream setDelegate:self];
[inputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
[outputStream setDelegate:self];
[outputStream setProperty:NSStreamNetworkServiceTypeVoIP forKey:NSStreamNetworkServiceType] ;
[inputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[outputStream scheduleInRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
[inputStream open];
[outputStream open];

}];

<强>3。假设我的服务器重新启动并且应用程序处于后台,我如何确保连接? 如果我的 iPhone 中的 Wi-Fi 连接或者我终止了服务器应用程序,则连接将被关闭,那么我应该采取什么措施来使我的应用程序按预期工作?

最佳答案

您还需要确保已在 pList 文件中设置

<key>UIBackgroundModes</key>
<array>
<string>voip</string>
</array>

当您的应用程序在后台时,套接字将由 iOS 管理。一旦套接字中有可用数据,您的应用程序就会收到 CPU 时间。所以在 runLoop 中我正在检查 ht

在我的例子中,信号协议(protocol)在一个单独的线程中工作,所以我自己旋转 runLoop

  // Start runloop
while (!m_needStop)
{
CFRunLoopRun();
}

并在需要时停止它:

  m_needStop = true;
{
QAutoLock l(m_runLoopGuard);
if ( m_runLoop != NULL )
CFRunLoopStop(m_runLoop);
}

对于 runLoop 中的套接字,我在将它们调度到 runLoop 之前设置了处理函数:

  int nFlags = kCFStreamEventOpenCompleted | kCFStreamEventHasBytesAvailable | kCFStreamEventCanAcceptBytes | kCFStreamEventErrorOccurred | kCFStreamEventEndEncountered;
CFStreamClientContext context;
context.info = this;
context.version = 0;
context.release = NULL;
context.retain = NULL;
context.copyDescription = NULL;

if ( !CFReadStreamSetClient(m_readStream, nFlags, NotificationProtocolHandler::ReadStreamCallback, &context) )
{
ReleaseStreams();
return false;
}

if ( !CFWriteStreamSetClient(m_writeStream, nFlags, NotificationProtocolHandler::WriteStreamCallback, &context) )
{
ReleaseStreams();
return false;
}

当您的套接字为您提供一些信息时,即使您的应用程序在后台,这些函数也会被调用:

void NotificationProtocolHandler::ReadStreamCallback(CFReadStreamRef stream,
CFStreamEventType eventType,
void *clientCallBackInfo)
{
NotificationProtocolHandler* handler = (NotificationProtocolHandler*)clientCallBackInfo;
switch (eventType)
{
case kCFStreamEventOpenCompleted:
break;

case kCFStreamEventHasBytesAvailable:
handler->ProcessInput();
break;

case kCFStreamEventErrorOccurred:
handler->ProcessConnectionError();
break;

case kCFStreamEventEndEncountered:
handler->ProcessConnectionError();
break;

default:
break; // do nothing
}
}

void NotificationProtocolHandler::WriteStreamCallback(CFWriteStreamRef stream,
CFStreamEventType eventType,
void *clientCallBackInfo)
{
NotificationProtocolHandler* handler = (NotificationProtocolHandler*)clientCallBackInfo;

switch (eventType)
{
case kCFStreamEventOpenCompleted:
handler->ProcessOutputConnect();
break;

case kCFStreamEventCanAcceptBytes:
handler->ProcessReadyToWrite();
break;

case kCFStreamEventErrorOccurred:
handler->ProcessConnectionError();
break;

case kCFStreamEventEndEncountered:
handler->ProcessConnectionError();
break;

default:
break; // do nothing
}
}

为了让服务器知道客户端仍然处于事件状态,我们每 10 分钟向服务器发送一次 ping 命令,因此 KeepAlive 处理程序设置为 600。您可以使用其他值来节省电池,但这会使断开连接的检测变得更糟在客户端和服务器端。并且会增加断开连接和重新连接之间的时间。

BOOL scheduled = [app setKeepAliveTimeout:pingTimeout handler:^{ // Schedule processing after some time interval      

SchedulePing(0);
}

SchedulePing(0) 将执行如下:

StartLongBGTask();
if ( avoidFinishBgTask != NULL )
*avoidFinishBgTask = true;
m_pingTimer = CreateTimer(pingTimeout, PingTimerCallback); // result is ignored

而 StartLongBGTask 是一个

m_bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler: ^{
[[UIApplication sharedApplication] endBackgroundTask:m_bgTask];
m_bgTask = UIBackgroundTaskInvalid;
}];

这是为了确保在发送 ping 并等待服务器对 ping 的回复之前应用程序不会被挂起。此外,如果套接字已经断开连接,则可能需要重新连接,这将需要一些时间并且需要进程在后台运行。

但请确保在不再需要后台任务时正确释放它们。否则,当超过 bg 超时时,应用程序将被系统杀死。

关于iphone - 如何在后台保持VOIP套接字连接?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5987495/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com