• • • • Avec des implémentations de SocketIO en java Communication Asynchrone (callback) Threads « masqués » Protocoles (échange des messages, contenus des JSON) à concevoir Côté Serveur Côté Client Synchronisation Aspect Pratique HTTPS://GITHUB.COM/MRNIKO/NETTYSOCKETIO SocketIOServer Le programme ne doit pas s’arrêter (par exemple, dormir jusqu’à « toujours »). c.f. cours sur les threads dans maven repository Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 02 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique <dependencies> <dependency> <groupId>com.googlecode.json-simple</groupId> <artifactId>json-simple</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>com.corundumstudio.socketio</groupId> <artifactId>netty-socketio</artifactId> <version>1.7.7</version> </dependency> <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-simple</artifactId> <version>1.7.7</version> </dependency> </dependencies> Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 03 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique // config com.corundumstudio.socketio.Configuration; Configuration config = new Configuration(); config.setHostname("127.0.0.1"); config.setPort(10101); // creation du serveur server = new SocketIOServer(config); Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 04 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique onConnect(SocketIOClient // abonnemement server.addConnectListener(this); arg0) onDisconnect(SocketIOClient arg0) server.addDisconnectListener(this); Nom du message Mapping message JSON / classe JAVA server.addEventListener("query", AddressQuery.class, this); onData(SocketIOClient arg0, AddressQuery arg1, AckRequest arg2) Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 05 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique public class AddressQuery { { address : "une valeur" } /* mapping JSON avec la classe : l'attribut (et les setter/getter) avec le champ JSON via introspection*/ private String address; public AddressQuery() { } public AddressQuery(String addresse) { super(); this.address = address; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 06 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • Méthode sendEvent de SocketIOClient – 1er paramètre : le nom du message (string) – 2e paramètre : un objet java « mapping » • En réponse à la connexion, à la réception d’un message… • Envoi à tous via getBroadcastOperations() de SocketIOServer – Idem : méthode sendEvent • Liste des connexions via getAllClients() de SocketIOServer Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 07 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique HTTPS://GITHUB.COM/SOCKETIO/SOCKET.IOCLIENT-JAVA io.socket.client.Socket Thread masqué (attention pour la mise à jour) c.f. cours sur les threads dans maven repository Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 08 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • Même librairie pour java « desktop » et pour « android » • Dépendance – graddle : compile ('io.socket:socket.io-client:0.8.3') { exclude group: 'org.json', module: 'json' } // car cela est dans le java android – maven : <dependency> <groupId>io.socket</groupId> <artifactId>socket.io-client</artifactId> <version>0.8.3</version> </dependency> Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 09 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • Se déconnecter dans onPause – Et se désabonner des messages (« off ») • Se (re)connecter quand nécessaire ou dans onResume • Création : Socket mSocket = IO.socket(serverAddress); //"http://192.168.1.23:10101"; //connexion mSocket.connect(); // abonnement aux messages « map » via Emitter.Listener mSocket.on("map", this); // pour annuler : mSocket.off("map"); Emitter.Listener --> call(Object... args) avec en 1er paramètre le JSON reçu Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 10 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique JSONObject obj = new JSONObject(); try { obj.put("nom attribut json", valeur); // etc. } catch (JSONException e) { e.printStackTrace(); } mSocket.emit("nom_message", obj); Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 11 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • L’envoi (et réception) asynchrone • Entre l’emit et l’envoi effectif : un délai (inconnu) • Si l’objet JSON est modifié entre temps… la version modifée sera envoyée (effet de bord) • Il est donc conseillé d’utiliser un nouvel objet (new) JSon à chaque emit Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 12 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • En troisième paramètre à emit, il est possible de mettre un écouteur qui sera rappelé une fois le message émis : mSocket.emit("chatevent", obj, new io.socket.client.Ack() { public void call(Object... arg0) { // code pour l’acknowledgment } }); Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 13 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • SocketIO utilise ses propres thread – L’émission est asynchrone (et exécuter sur un thread de SocketIO) – La réception se fait sur un thread « EventThead » de SocketIO • Il y a des besoins de synchronisations – S’il faut attendre la fin de l’émission – Ou s’il faut accéder à des ressources d’un autre thread (graphique) lors de la réception Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 14 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique mSocket.emit("evt", obj, new io.socket.client.Ack() { public void call(Object... arg0) { // code de l’ACK... mais en dernier : synchronized (synchro) { synchro.notify(); } } }); • Dans le Ack de l’émission, on termine par un notify // attente de l'envoi confirmé du message synchronized (synchro) { try { synchro.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } • Dans le thread qui a fait « emit », on attend Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 15 / 20 Côté Serveur Côté Client Depuis le thread graphique • wait / notify possible, mais risque de bloquer l’application • Création d’un thread new Thread(runnable) – Dans le « run » : emit puis wait • Il y a donc « 3 » thread : Synchronisation Aspect Pratique Vers le thread graphique • Réception via un thread de SocketIO (pas d’accès aux éléments graphique) – Ou cas du thread intermédiaire ci-contre • Utilisation des handlers du thread principal : – « runOnUiThread » d’Activity – Méthode « post » des View – Le thread graphique – Qui lance un thread (pour les emit) – Le (ou les) thread de SocketIO Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 16 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • Fichier partagé avec vos comptes (salles de tps) • Accessible depuis l’extérieur (mais pas ssh) • Des ports ouverts (y compris sur hot-spot) 10102 à 10131 Un port affecté par groupe !! • Accessible via ssh depuis polymnie (sesame-mips.unice.fr) (et les machines des salles de tps) – Clef ssh (pas forcément la même que pour connexion) : la privée et la publique sont les deux dans .ssh (partage de fichier) – ssh tpsi -i .ssh/clef_specifique_privee Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 17 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • Accès ssh – Clef publique / privée – Clef ssh (à générer sous linux, éventuellement à convertir pour windows) – http://www-crips.unice.fr/CRIPS/FAQetudiants/Connexion_au_serveur_sesame.pdf • Puis ssh sur les machines des salles de tp (comme olivier, basset, etc.) : environnement de travail avec git, etc. • Puis ssh sur tpsi (pour exécuter le server) Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 18 / 20 Côté Serveur Côté Client Synchronisation Aspect Pratique • Le serveur est dans le jar « serverIO.jar » – La classe principale : server.Server – Qui prend : l’IP du serveur et le port – En classpath (-cp) : le jar serverIO.jar et toutes les librairies java -cp serverIO.jar:libs/jackson-annotations-2.4.0.jar:libs/jackson-core2.4.3.jar:libs/jackson-databind-2.4.3.jar:libs/netty-buffer-4.0.25.Final.jar:libs/nettycodec-4.0.25.Final.jar:libs/netty-codec-http-4.0.25.Final.jar:libs/netty-common4.0.25.Final.jar:libs/netty-handler-4.0.25.Final.jar:libs/netty-socketio1.7.7.jar:libs/netty-transport-4.0.25.Final.jar:libs/netty-transport-native-epoll4.0.25.Final.jar:libs/slf4j-api-1.7.7.jar:libs/slf4j-simple-1.7.7.jar:. server.Server 134.59.2.27 10101 Toutes les dépendances (dans libs/) se téléchargent via maven (c.f. après) (mettre la ligne dans un fichier exécutable u+x) Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 19 / 20 Côté Serveur Côté Client Synchronisation Dans le pom.xml : ajout d’un plugin <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-dependency-plugin</artifactId> <version>3.0.0</version> <executions> <execution> <id>copy-dependencies</id> <phase>package</phase> <goals> <goal>copy-dependencies</goal> </goals> <configuration> <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory> <overWriteReleases>false</overWriteReleases> <overWriteSnapshots>false</overWriteSnapshots> <overWriteIfNewer>true</overWriteIfNewer> </configuration> </execution> </executions> </plugin> Aspect Pratique • Utilisation en ligne de commande : mvn dependency:copy-dependencies -DoutputDirectory=DOSSIER_OU_COPIER • Source : http://maven.apache.org/plugins/mavendependency-plugin/examples/copyingproject-dependencies.html Server / Client en java avec SoketIO - L3 Informatique - Projet de Licence (Info) / Projet de Développement (Miage) - Semestre 6 20 / 20