18
votes

I am using PHP to connect to apns to send some notifications to multiple devices, although the question is more conceptual so it doesn't have to be specific to PHP.

I will be sending to about 7000 devices (and growing) all at the same time. My process runs ONCE per day and broadcasts to all devices, so I am not constantly re-opening a connection.

Currently I can easily send to 2 devices at a time and the messages will successfully deliver. However when I attempt to send to the full 7000 devices, the messages do not seem to deliver.

The pseudo-logic to my code is:

open connection to apple
loop over device-tokens
    write to socket connection per device
end loop
close connection to apple.

I have seen somewhere that I should only perform a SINGLE write, and construct one huge body, in other words the pseudo-code would look like:

loop over device tokens
    create payload aggregating all devices
end loop
open connection to apple
write to socket ONCE with whole payload for 7000 devices
close connection

It's difficult to test as I obviously can't spam my 7000 production users with test messages. Has anybody else had a similar problem?

Thanks

2
did you ever get this working? I will soon be writing an app that will be facing the same issue -- broadcast to thousands of clients through APNS.Mike Morearty
Hi Mike. Yes I did. The implementation at the time that i posted this question was in the fairly early stages. The problem was that I had some sandbox devices in the same table as production devices. Apple sometimes drops the connection if you send to a sandbox device_token while using production certs. So the simple solution is to just verify that the correct number of bytes was written to the connection and that the connection has not dropped after every write event. If it drops you have to re-open the connection and continue from where you left off. good luck!BoomShaka
FYI, you can open the connection and perform as many writes as you like. just make sure you check the connection status after each writeBoomShaka
is it possible to broadcast push message to multiple devices? Can i aggregate the tokens as you mentioned above and send one message to all devices?Itay Levin
Err yes, that's exactly what I'm doing above. I collect all the tokens in a database table, and then once per week I send the same message to all devices (the message could even be customised per device. You will have to send a seperate payload to the APNS per device though. SO if you have 100 devices, thats 100 writes to the socketBoomShaka

2 Answers

6
votes

I've read that apple does care about the number of connections you make to their servers but I've never heard about any write limits. Also, I'm not sure about what kind of response you'd receive here, but it might be worth a try to see what happens. Maybe experiment with the sandbox push notification server, only using the device tokens of the production devices. Those phones should not receive any push notifications sent to the sandbox server and if the sandbox reports "delivered successfully", that would be a worry-free way to test.

0
votes

I see what you want and rather, i did face the same problem, what worked for me was the reverse engineering. I just looked into the library and checked for the function which validates the deviceToken. So while creation of dummy device token i just made sure that the generated token is valid as per the library.

The following code will let you generate valid device Tokens, now its on you to how many millions of tokens to generate using this function.

   def generateRandomDeviceTokenAndAppendItToJson(tokenLength: Int) {
     val randomlyGeneratedDeviceToken = new StringBuilder()
      randomlyGeneratedDeviceToken.append("          \"")
        (1 to tokenLength) foreach {
         times: Int =>
        if (tokenLength equals Device.Apple)
         randomlyGeneratedDeviceToken.append(validCharacter().toString.charAt(0))
        else
         randomlyGeneratedDeviceToken.append(Random.alphanumeric.head)
        }
       randomlyGeneratedDeviceToken.append("\",")
       println(randomlyGeneratedDeviceToken)
       writer.write(randomlyGeneratedDeviceToken.toString())
      }

      private def validCharacter(): Int = {
       val a = Random.alphanumeric.head
       if ('0' <= a && a <= '9')
        return (a - '0')
       else if ('a' <= a && a <= 'f')
        return ((a - 'a') + 10)
       else if ('A' <= a && a <= 'F')
        return ((a - 'A') + 10)
       validCharacter() 
     }

The apple deviceToken is of 64 character so you will need to iterate on it for 64 times.