1

I am working on a simple web server that sends push notification to my iPhone app. I've tried using existing Python packages, but they all suffer from this problem:

When an invalid token is sent, Apple will send back a error message and close the socket. I need to send a large number of push notifications, but if one of them has an invalid token, the rest won't be delivered to Apple.

So currently, my code looks something like this:

for m in messages:
    socket.send(m)

But when the first of the messages has invalid token, so Apple closes the socket as soon as it receives the first message, socket still sends all the messages without any error.

I can't afford to do a recv after each message with a timeout, since that will take too long. What can I do to know when the socket is closed and open a new one?

Barum Rho
  • 2,743
  • 1
  • 20
  • 21

2 Answers2

1

If the socket had been closed on the other end a recv on it should return 0 or result in an error.


You could check the number of bytes sent by send.


Update: You might like to read here on another possibilty to monitor if a socket connection is still alive.


Update-1: Another approach might by to run a constantly reading thread on the socket in question in parallel to the write operation ... as you mention: time is your limit.

Community
  • 1
  • 1
alk
  • 69,737
  • 10
  • 105
  • 255
  • I tried checking bytes sent, but they look like they were all sent. – Barum Rho May 06 '12 at 06:36
  • *sigh* - yes, this could happend. See my updated comment for a link to a dicsussion on a possible more reliable solution using the Keep-Alive socket option. @BarumRho – alk May 06 '12 at 07:03
  • Thanks for your answer, but I don't think Keep-Alive will solve my problem. – Barum Rho May 06 '12 at 07:32
  • Yes, I thought about running another thread to poll for any incoming packets, but even then, I wouldn't know what packets were sent. I posted what I decided to do below. – Barum Rho May 06 '12 at 07:39
0

I learned that there is no way at TCP level that I can find out what packets were sent. I decided to just send all the messages and then wait (with timeout) for any error messages from Apple. If there is any error, repeat sending the ones that failed.

I decided to go with this, since getting an invalid token should be a rare event, and most of the time all the notifications will go through.

Barum Rho
  • 2,743
  • 1
  • 20
  • 21
  • This is a good way of detecting whether you sent a malformed packet or not. It does not catch situations where the socket has closed on the far end, for whatever reason it may be. For that scenario, you're stuck in the situation @alk alludes to. – YWCA Hello Apr 03 '13 at 20:50
  • I'm not sure how great of a solution this is in terms of performance. Waiting only 1 second has seriously performance implications, and yet you aren't guaranteed to hear back from Apple within this period. – Martin Konecny Nov 26 '14 at 22:12
  • @MartinKonecny: It's true. In my case it worked out okay because I was sending big batches. I am not sure if there is any other way around it though. – Barum Rho Dec 12 '14 at 19:11
  • I think a better way is to have two threads, one for writing to a socket and one for listening. The listening thread will use `select` to listen to a list of sockets and return a subset of those sockets which are ready for reading. See here: http://www.ruby-doc.org/core-2.1.5/IO.html#method-c-select – Martin Konecny Dec 12 '14 at 19:44