在 iPhone 上发送 UDP 数据包在新的 3G 连接上失败,但可以正常工作
当我通过 3G 从 iPhone 发送 UDP 数据包时遇到一个奇怪的问题。几乎每次我的应用程序在较长时间的网络不活动后启动(例如,手机从睡眠模式恢复或刚刚获得 3G 连接后),我的应用程序都无法发送任何 UDP 数据包。我从 CFSocketSendData
收到 kCFSocketError
错误状态。然后,应用程序逻辑每五秒重新尝试定期发送数据包,但无论我让它运行多久,它总是失败。但是,当我将应用程序切换到后台并在 Safari 中打开网页时(当应用程序在后台仍然失败时),应用程序突然开始工作。基本上,其他网络活动(来自 Safari、地图等)似乎“真正启动了网络”。例如,我需要在网络初始化方面做一些特殊的事情吗?
这是我用来发送 UDP 数据包的代码的简化片段:
CFSocketRef cfSocket = CFSocketCreate(NULL, 0, SOCK_DGRAM, IPPROTO_UDP, kCFSocketNoCallBack, NULL, NULL);
if (!cfSocket)
{
// snip: some error handling
}
struct sockaddr_in addr;
// snip: init addr
CFDataRef cfAddr = CFDataCreate(NULL, (unsigned char *)&addr, sizeof(addr));
CFSocketError sendPacketResult = CFSocketSendData(cfSocket, cfAddr, cfPacketData, 0.0);
if (sendPacketResult != kCFSocketSuccess)
{
// try again in 5 seconds
}
在 Wi-Fi 上一切正常,没有任何问题。
公平地说,我认为我有时(但非常偶尔)在标准 iPhone 应用程序(Safari、地图等)中也看到过相同的行为。有时他们拒绝连接(即使我看到了 3G 图标),我需要关闭并重新打开它们。但这种情况非常罕见。
编辑:可能相关的问题:在 iPhone 上,EPERM (errno == 1) 在响应 send() 时意味着什么UDP 数据?。
I'm having a strange problem when sending UDP packets from an iPhone over a 3G. Almost every time my application starts after a longer period of network inactivity (for instance after the phone comes from the sleep mode or it just gets a 3G connection), my application is not able to send any UDP packets. I get a kCFSocketError
error status from CFSocketSendData
. The application logic then re-tries to send the packet periodically every five seconds, but no matter how long I let it run it keeps failing. However, when I switch the application to background and open, for instance, a web page in Safari (while the application is still failing on background), the application suddenly starts working. Basically, it seems like the other network activity (from Safari, Maps etc.) "kicks off the networking for real". Do I need to do anything special in terms of network initialisation for instance?
This is a simplified snippet of the code I'm using to send the UDP packets:
CFSocketRef cfSocket = CFSocketCreate(NULL, 0, SOCK_DGRAM, IPPROTO_UDP, kCFSocketNoCallBack, NULL, NULL);
if (!cfSocket)
{
// snip: some error handling
}
struct sockaddr_in addr;
// snip: init addr
CFDataRef cfAddr = CFDataCreate(NULL, (unsigned char *)&addr, sizeof(addr));
CFSocketError sendPacketResult = CFSocketSendData(cfSocket, cfAddr, cfPacketData, 0.0);
if (sendPacketResult != kCFSocketSuccess)
{
// try again in 5 seconds
}
It all works fine without any problems over Wi-Fi.
To be fair, I think I've seen sometimes (but very occasionally) the same behaviour in the standard iPhone applications (Safari, Maps, ...) as well. Sometimes they refuse to connect (even thought I see the 3G icon) and I need to close and reopen them. But it's very rare.
Edit: Possibly related question: On iPhone, what does EPERM (errno == 1) mean in reponse to send() of UDP data?.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
3G TCP/IP 网络接口可以根据操作系统的意愿被 IOS 关闭,通常是出于省电的原因(如果没有流量通过该接口)。当使用 BSD 套接字时(例如,对于 UDP,因为没有 UDP 苹果网络框架),没有已发布的操作系统调用来确保 3G 网络接口正常运行。但在 Apple 的 CFSocketStream 类内部,存在唤醒接口的私有 Apple 调用。
所以解决方案似乎是向某个地方打开一个CFSocketStream。这将唤醒接口一段时间。只要您每分钟左右通过 CFSocketStream 发送一次数据,连接和网络接口就会保持正常状态。
这并不是那么有吸引力,因为它只是通过副作用起作用。但这似乎是目前唯一的解决方案。
The 3G TCP/IP network interface can be torn down by IOS at the operating system's pleasure, generally for power-saving reasons if there is no traffic going across it. When using BSD sockets (for example, for UDP, since there is no UDP apple networking framework) there's no published OS call for ensuring the 3G network interface is up. But internally in Apple's CFSocketStream class there exists private Apple calls that wake up the interface.
So the solution seems to be to open up a CFSocketStream to someplace. That will wake up the interface for some period of time. As long as you send data over the CFSocketStream once a minute or so the connection and the network interface will stay up.
This isn't all that attractive, since it's only working by side effect. But it seems to be the only solution at this point.