SIGPIPE error in iOS4 when app is running background and lock screen - iphone

I use BSD socket in my app to send and receive data on iphone4(iOS4.1),there are three situations in my app:
app is running in foreground and screen locks, it's fine.
app is running in background and screen does't lock, it's fine too(I use NSStream to send and receive data for keep app alive in background,it works fine.)
app is running in background and screen locks, app running fine but always get the SIGPIPE error when app try to call sendto() or send() through UDP or TCP socket.
I search a lot but get nothing useful,from here i know what SIGPIPE is , and i use setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(int)) to avoid app exit abnormally. but i still don't know why this error occurred only in situation 3 and how to send data normally through bsd socket in this situation.
I have try to renew and reconnect but it does't work,it still get SIGPIPE error.
I think it maybe that all BSD sockets cannot get internal access in situation 3(As far as we know that BSD socket cannot activate wifi or EDGE connection in iOS),Anyone can help me or give me some suggestions? and sorry for my Broken English^.^,Thank you very much .

I search on google and found my own question 10 months before, that's interesting.
I already had a solution for application keep running in background , and setsockopt(sock, SOL_SOCKET, SO_NOSIGPIPE, (void *)&on, sizeof(int)) is useful which will ignore Sigpipe 13 error .
this error happens when the socket already lost physical connection and still try to write data,through Wifi, 3G or Accessory.

Related

Socket connection from WatchOS 2 and CFStream

I have to connect a remote server via tcp socket from the Watch.
I have already written a piece of code using CFStream which works perfectly from the Watch simulator.
When I run it on the Watch I get this error:
The operation couldn’t be completed. Can't assign requested address (Code = 49)
when I try to open the connection to the server using CFStreamCreatePairWithSocketToHost.
The Apple documentation declares that CFStreamCreatePairWithSocketToHost is
Available in watchOS 2.0 and later.
so I expected that it had should work but I have found this Apple's engineer answer which confirms that there is no way to open a tcp connection from the Watch:
Socket communication does not work real Apple Watch
Can anyone clarify and help me to understand?
Supposing that I cannot open a tcp connection from the Watch, what kind of alternatives have I, since I cannot use [NSURLSession]?
I could use one of the communication methods provided by [WCSession] but do they work when the iPhone app either is not running or is not in foreground?
You could use WCSession's sendMessage APIs to wake the iOS app up in the background and have it do the Stream work for you.

iPhone sometimes fails connecting to cc2564 (Bluetooth Low Energy)

We are developing an application where an iPhone should connect to an cc2564 device (Specifically cc2564+msp430f5438), the application should make quick and short connections to send some data. We need reliability in the connection so we need to know if the connection was really successfully or not, and we need a way to connect to the device with assurance.
The iPhone connects correctly to de device most times, it discovers services and works as expected, but sometimes the iphone makes the connection but the callback of discovered services is never called.
We used a sniffer to look at the communication packages and we saw that in those cases the connection package was send but there wasn't any response from the device, the phone tries to retry some version request messages and then stops, as you can see in the image:
The problem seems to be on the device, we are using the SPPLEDemo sample provided by Texas, and the first function that is called when the connection is established is GAP_LE_Evenet_Callback, and when the problem occurs it's never called. We don't know if somewhere inside the GAP API the device receive the connection message.
Is there some way to debug it or to know if the connection message is received by the device when the error occurs?
Is it a problem on the iPhone (unlikely), or is a problem on the device?
You quoted that
..the first function that is called when the connection is established is GAP_LE_Evenet_Callback, and when the problem occurs it's never called..
I'd recommend tweaking (playing) a bit with connection timeouts and Link Supervision Timeouts before consulting the experts who have developed the BLE Device firmware if that is possible for you.
Be assured that whenever a connection is made, the BLE device gets an event (callback) from the BLE stack that the connection has been established.
If that event is not handled the way it should be, then you can conclude that BLE device has some implementation issue.

UDP sendto() No buffer space available

I'm trying to create an iOS application that sends data over UDP continuously over wifi/3G network.
I have an issue when I launch my app over 3G network after like 10 seconds I get this message :
sendto() : No buffer space available
It's not that a big deal because my app still works well BUT when I quit the app, I guess my buffer stays full because I can't use 3G anymore (I have to wait some time or reboot my phone)
Is there a way to flush this buffer before I quit my app ?
It sounds as if you're hitting the outbound bandwidth limit. If your app does this continuously while in use, isn't that going to make it very expensive for users to run? Most mobile users, I would guess, are on some kind of metered plan where they pay for transferred data.
I would guess that closing the socket normally before exiting should flush it first, since you've requested the data to be sent after all, but sometimes UDP sockets don't try very hard to deliver the data (since they are "lossy"), perhaps that's what's happening in your case too.

How to properly *connect* background socket at iPhone startup in a VOiP application?

I'm using a VOiP Socket in my iPhone application. I manage to get it working properly, both in background mode, or when the application is in the foreground.
My issue is at iPhone startup: how to be sure that the iPhone has network access (3G or wifi) in order to properly connect the socket without bothering the user ?
Details: a VOiP application is supposed to be started automatically as soon as the iPhone starts : this is working ok, the didFinishLaunching is invoked right after the iPhone startups. But at this time, the user may not have entered his pin code (so that 3G isn't available) and wifi may not be available.
Is there any technique to start automatically the VOiP Socket when network access is ok ?
My current approach that fails : in the didFinishLaunching I keep on trying to start the VOiP socket every 5 secs. If it takes too long without managing to get the connection, the OS is going to kill the app, (max 20s to start), but as the app is flagged as "VOiP", it's going to be started again, and so on...
After a while, once network is OK, the socket is being created , connected and everything seems to works ok, EXCEPT that when data comes to the socket, my callback didReceivedData is not invoked (I display a local notification as soon as I get something from the socket for debug purpose) .
Then, if I start the application just 1 time, and then quit it (home button), so that the application is put in the background, in that case, the socket callback is properly invoked and I see local notifications being displayed, proof that the socket is properly waken up in that case.
I would like to get the VOiP socket up and running right from iPhone startup (once network is OK) without having the user to launch the application 1 time. Any idea about how to achieve this ?
Use the Reachability class to poll for connectivity every X seconds, THEN try to connect.
Reachability won't take as long as creating the VoIP socket will.

Sending UDP packets on iPhone fails over a fresh new 3G connection, but works otherwise

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?.
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.