J'essaie de mettre en œuvre la prise en charge du format de message Push Notification amélioré d'Apple dans mon application Rails, et je rencontre quelques problèmes frustrants. Il est clair que je ne comprends pas les sockets autant que je le pensais.
Mon principal problème est que si j'envoie tous les messages correctement, mon code se bloque, car socket.read se bloque jusqu'à ce que je reçoive un message. Apple ne renvoie pas tout ce qui est si vos messages semblaient corrects, alors mon programme se bloque.
Voici le pseudo-code de mon fonctionnement :
cert = File.read(options[:cert])
ctx = OpenSSL::SSL::SSLContext.new
ctx.key = OpenSSL::PKey::RSA.new(cert, options[:passphrase])
ctx.cert = OpenSSL::X509::Certificate.new(cert)
sock = TCPSocket.new(options[:host], options[:port])
ssl = OpenSSL::SSL::SSLSocket.new(sock, ctx)
ssl.sync = true
ssl.connect
messages.each do |message|
ssl.write(message.to_apn)
end
if read_buffer = ssl.read(6)
process_error_response(read_buffer)
end
Évidemment, cela pose un certain nombre de problèmes :
- Si j'envoie des messages à un grand nombre de dispositifs et que le message d'échec est envoyé à mi-chemin du traitement, je ne verrai l'erreur que lorsque j'aurai essayé d'envoyer le message à tous les dispositifs.
- Comme mentionné précédemment, si tous les messages étaient acceptables pour Apple, mon application se bloquerait sur l'appel de lecture de la socket.
J'ai essayé de résoudre ce problème en lisant le contenu du socket dans un thread séparé :
Thread.new() {
while data = ssl.read(6)
process_error_response(data)
end
}
messages.each do |message|
ssl.write(message.to_apn)
end
ssl.close
sock.close
Cela ne semble pas fonctionner. Les données ne semblent jamais être lues depuis le socket. Il s'agit probablement d'un malentendu sur la façon dont les sockets sont censés fonctionner.
L'autre solution à laquelle j'ai pensé est d'avoir un appel de lecture non bloquant... mais il ne semble pas que Ruby ait un appel de lecture non bloquant sur SSLSocket avant la version 1.9... que je ne peux malheureusement pas utiliser pour le moment.
Quelqu'un ayant une meilleure compréhension de la programmation des prises pourrait-il m'indiquer la bonne direction ?