根据apple文档,我们必须为VoIP使用配置一个app socket.我无法弄清楚如何配置C套接字(因为有许多套接字;即SSL,SIP,RESTful).
目的是在睡眠模式下运行应用程序,直到它被杀死.从SO中尝试了几个链接甚至几个链接,但由于我是新手,我希望这个配置有一步一步的过程.
[注意:在某个地方我发现了CoreFoudation框架,我是否需要使用它?]
解决方法
有关开发VoIP应用程序的提示,参考自Apple
互联网协议语音(VoIP)应用程序允许用户使用互联网连接而不是设备的蜂窝服务拨打电话.这样的应用程序需要维持与其关联服务的持久网络连接,以便它可以接收传入呼叫和其他相关数据.系统不是让VoIP应用程序始终保持唤醒状态,而是允许它们被暂停,并提供监视其套接字的工具.当检测到传入流量时,系统唤醒VoIP应用程序并将其套接字的控制权返回给它.
实施VoIP应用有几个要求:
>为您的应用启用Voice over IP后台模式. (由于VoIP应用涉及音频内容,因此建议您还启用音频和AirPlay背景模式.)您可以在Xcode项目的“功能”选项卡中启用后台模式.
>为VoIP使用配置其中一个应用程序的套接字.
>在移动到后台之前,调用setKeepAliveTimeout:handler:方法来安装要定期执行的处理程序.您的应用可以使用此处理程序来维护其服务连接.
>配置音频会话以处理往返过渡
积极使用.
>要确保在iPhone上获得更好的用户体验,请使用Core Telephony
用于调整与基于手机的手机相关的行为的框架
电话;请参阅核心电话框架参考.
>要确保VoIP应用程序的良好性能,请使用系统
配置框架,用于检测网络更改并允许您的应用
尽可能多地睡觉
启用VoIP后台模式可让系统知道应该允许应用程序根据需要在后台运行以管理其网络套接字.此键还允许您的应用播放背景音频(尽管仍然鼓励启用音频和AirPlay模式).支持此模式的应用程序也会在系统启动后立即在后台重新启动,以确保VoIP服务始终可用.
下面的代码显示了如何为VoIP使用配置应用程序的套接字.
第1步:连接到服务器
uint16_t port ; Nsstring *strIp ; char ip[20] = {0} ; memset(ip,sizeof(ip)) ; memcpy(ip,[strIp UTF8String],[strIp length]) ; clientSocket = socket(AF_INET,SOCK_STREAM,0) ; struct sockaddr_in server_addr ; bzero(&server_addr,sizeof(server_addr)) ; server_addr.sin_port = htons(port) ; server_addr.sin_addr.s_addr = inet_addr(ip) ; server_addr.sin_family = AF_INET ; int i = connect(clientSocket,(const struct sockaddr *)&server_addr,sizeof(server_addr)) ; if (i >= 0) { }
服务器端代码可能在C环境中,但您可以将clientSocket传递给Objective-C实例,它是一个int值.
第2步:创建和配置读写流
连接到服务器后,您需要创建一个读取&使用CFStreamCreatePairWithSocket()基于clientSocket编写流,并使用NsstreamNetworkServiceTypeVoIP设置流的属性.
定义读写流并保持强引用.连接丢失时关闭并释放它们.
@property (nonatomic,strong) NSInputStream *inputStream ; @property (nonatomic,strong) NSOutputStream *outputStream ;
然后配置流:
CFReadStreamRef readStreamRef = nil ; CFWriteStreamRef writeStreamRef = nil ; CFStreamCreatePairWithSocket(NULL,clientSocket,&readStreamRef,&writeStreamRef) ; // the socket must have already been connected. _inputStream = (__bridge_transfer NSInputStream *)readStreamRef ; _outputStream = (__bridge_transfer NSOutputStream *)writeStreamRef ; [_inputStream setProperty:NsstreamNetworkServiceTypeVoIP forKey:NsstreamNetworkServiceType] ; [_outputStream setProperty:NsstreamNetworkServiceTypeVoIP forKey:NsstreamNetworkServiceType] ; [_inputStream open] ; [_outputStream open] ;
在连接read& amp;之前,确保已连接插座.写流.
第3步:保持连接
[[UIApplication sharedApplication] setKeepAliveTimeout:600 handler:^{ // the code to check if the socket is connected to server // if not,reconnect to server // and re-set the read stream and write stream in step2 }] ;
当您的应用程序进入后台时,套接字由系统管理,当服务器将数据包发送到您的应用程序时,系统将其唤醒,将数据包传递给它.你只有几秒钟来处理数据,所以这里做不了多少工作.由于它是一个VoIP应用程序,因此套接字应该用于通知用户呼叫是传入的,您可以推送本地通知以使用户意识到这一点.
由于VoIP应用程序需要保持运行才能接收来电,因此如果应用程序以非零退出代码退出,系统会自动重新启动应用程序. (当存在内存压力且您的应用程序因此终止时,可能会发生此类退出.)但是,终止应用程序还会释放其所有套接字,包括用于维护VoIP服务连接的套接字.因此,当应用程序启动时,它总是需要从头开始创建其套接字.
我创建了一个示例项目here,相关的服务器端代码here.