Socket Java: Pousser les demandes au client via socket


Je crée actuellement une application client-serveur qui est principalement construite pour faire un appel de procédure à un serveur et attendre une réponse de paquet.

Cependant, je voudrais que le serveur 'envoie' des nouvelles au client (à un moment spontané), mais cela semble être un problème si le message arrive lorsque le client écoute une autre réponse de paquet.

Existe-t-il un moyen de diviser un socket en 2 flux de canaux uniques, via la même instance de socket? Ou serait-il mieux de faire un thread client qui n'écoute les connexions entrantes et les envoie à une file d'attente?

Quels sont les modèles et pratiques courants lorsque vous travaillez avec une connexion client-serveur 2 voies? (Où les flux se produisent spontanément)

Pour les rappels, j'utilise Java Socket, ObjectInputStream et ObjectOutputstream. je ne suis pas à l'aide de Java RMI.

Author: Mike Pennington, 2012-11-07

2 answers

Donc, l'une des choses que vous rencontrerez lors de l'apprentissage de la mise en réseau est la perte de synchronisation. Cela se produit lorsque vous "codez en dur" un certain ensemble d'interactions client-serveur, par exemple;

server sends 2 byte status code
client receives 2 byte status code
client responds with 4 byte operation code

Si, pour une raison quelconque, il y a un bogue qui fait qu'une partie de cette interaction ne se produit pas exactement comme il le faut, alors le rest du programme échoue car toutes les interactions réseau sont maintenant désynchronisées. Le client peut lire un ensemble d'octets qu'il croit représente une chaîne, quand vraiment le serveur envoie un int, et ainsi de suite. Le pire de tout, vous pourriez trouver que vos threads réseau principaux sont dans l'impasse car le client et le serveur attendent l'entrée en même temps.

Avec un projet plus grand, où il y a certainement des bugs, ce se produira énormément si vous codez dans ce style. Pour cette raison, nous avons quelque chose appelé middleware .

Un paradigme middleware très commun et flexible est le TLV Protocole de Message. Vous implémenteriez des classes simples (en semi-java-pseudocode);

TLVMessage
    int type;
    byte[] value;

TLVPusher implements Runnable
    OutputStream out;
    Queue<TLVMessage> messages;
    run() {
        while(true) {
            //poll and write front of queue to out (INCLUDING value.length!)
        }
    }

TLVReader implements Runnable
    InputStream in;
    Queue<TLVMessage> messages;
    run() {
        while(true) {
            //read message from in and add to queue
        }
    }

Maintenant, vous avez deux threads en cours d'exécution sur le client, et deux threads s'exécutant sur le serveur. Chaque fin a ses propres Pusher et Reader. La chose importante à noter est que parce que vous écrivez le champ length dans le flux de sortie, le lecteur sait toujours combien d'octets il doit lire. Donc, même si un message a été sérialisé incorrectement, sa longueur est toujours correcte et le message suivant sera toujours lu correctement du premier octet au dernier. De cette façon, votre programme ne peut jamais se désynchroniser.

Vous ajoutez simplement des objets TLVMessage au pusher.queue, et ils arriveront au reader.queue à l'autre extrémité du socket. Vous pouvez ensuite gérer les messages (dans un autre, troisième, thread qui surveille reader.messages.size()) par leur champ type.

Vous n'avez pas à vous soucier de l'ordre dans lequel les choses se passent, vous avez un mécanisme robuste pour passer des messages entre le client et le serveur, dans deux directions. Vous avez résumé les trucs de réseau difficiles et pouvez simplement continuer à coder.

Il y a bien sûr des bibliothèquesqui font tout cela pour vous, mais cela vaut toujours la peine de comprendre le commentet le pourquoi à mon avis.

 1
Author: lynks, 2012-11-07 10:37:24

Devez-vous coder directement dans les sockets? Cela semble être un bon candidat pour aller plus haut dans la pile OSI et utiliser eg. JMS pour atteindre votre objectif.

J'espère que cela aide.

Bravo,

 0
Author: Anders R. Bystrup, 2012-11-07 08:56:10