IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Entrée/Sortie Java Discussion :

[Serialisation]Transfert d'objet(s) par un socket


Sujet :

Entrée/Sortie Java

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut [Serialisation]Transfert d'objet(s) par un socket
    Bonjour,

    C'est la premiere fois que je poste sur ce forum, je passe beaucoup de temps a lire les reponsses postees aux messages et ayant un probleme plutot particulier je me suis permis de m'inscrire et de vous presenter mon probleme.

    j'ai deux programmes, un client et un serveur.

    Suite a un echange le serveur verifie si le client connait bien le mot de passe pour acceder au serveur, puis il verifie la version du client (soucis de compatibilitees) puis il lui envoie un objet de type Univer issue d'une deserialisation du fichier "Univer1.exp" qui a ete lui meme serialise plus tot. Mon soucis est que une fois tranfere vers le client j'ai une jolie:

    java.io.EOFException
    at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2279)
    at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2748)
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)
    at main.support.network.ServerQuery.run(ServerQuery.java:103)

    le serveur lui indique que le transfert c'est bien passe, mais impossible pour le client de faire quoi que se soit avec cet objet.
    J'ai vu sur Internet un post expliquant que l'objet tranfere ete en faite une sorte de lien vers l'objet en memoire mais que lors de son tranfert le lien n’était plus valide puisque l'objet n'existe pas sur le client, or c'est pourtant par ce système que ça fonctionne.

    En gros je suis un peu perdu, si vous souhaitez plus de detail aucun soucis, je reposte le plus vite possible.

    merci

  2. #2
    Membre Expert

    Homme Profil pro
    Consultant informatique
    Inscrit en
    Janvier 2004
    Messages
    2 301
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : Finance

    Informations forums :
    Inscription : Janvier 2004
    Messages : 2 301
    Par défaut
    Hello, et bienvenue sur le forum.

    Un peu de code pourrait sûrement nous aider...

    Pour l'instant, les seules pistes que j'ai en tête sont:

    1) sérialisation incomplète de l'objet (év. les flux n'ont pas été flushés et fermés correctement lors de l'écriture du fichier)
    2) transfert partiel des données (peut-être que le volume généré est important, et qu'un genre de "timeout" fait que toutes les données n'arrivent pas assez vite pour être utilisées). Si c'est cela, il faudrait mettre en place un système de buffer ou de fichier temporaire chez le client, et ne commencer à désérialiser que lorsque l'on est sûr que tout est arrivé.

    Enfin bref, sinon il faudrait mémoriser dans un fichier les données reçues par le client et les comparer avec celles du fichier original, peut-être que tu pourras voir des choses intéressantes de cette manière


  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut a tester...
    Oui je pensais aussi a un transfert incomple ce qui serait possible. Pour l'histoire du time out tu vient de me donner une idee, en effet le time out est fixe deja tres tres haut , a savoir: 10 secondes
    mais toutes les 5 secondes , la ca devient interessant, jai un thread nomme ping qui comme son nom l'indique test si le client est toujours la. je vais le desactiver, si ca fonctionne je vous le dis et sinon je selectionnerai les bouts de codes qui je l'espere pourront aider.
    merci, je reposte dans pas longtemps.

  4. #4
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut Bon bon.
    Apparemment ce n'etait pas le ping qui interferait avec le transfert, je poste donc des bouts de codes, mais je peut pas poster l'ensemble ca risque d'etre indigeste

    Donc cote serveur:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    log.info(login+" go in: "+univer);
    						fluxSortie.println("OK");
    						fluxSortie.flush();
    						fluxSortie.println("UNIVER");
    						fluxSortie.flush();
    						//on envoie l'univers
    			            OutputStream os = serviceSocket.getOutputStream();
    			            ObjectOutputStream oos = new ObjectOutputStream(os);
     
    			            Univers test=loadUnivers("data/univers/"+univer+".exp");
     
    			            log.info("Send : "+univer+" to client : "+login+" ...");
    			            oos.writeObject(test);
    			            oos.flush();
    			            log.info("Send : "+univer+" to client : "+login+"  OK!");
    			            oos.close();
    			            os.close();
    je commente un peu:
    tout les fluxSortie ecris en gros caracteres sont des commandes envoyees au client, tout commence a UNIVER ce qui indique au client que le prochaint flux sera l'objet serialise, cet objet arrive de loadUniver qui est une methode qui recupere un univer serialise a partir d'un fichier. On envoie le tout et hop c regle. Du cote serveur tout fonctionne sans soucis, par contre......

    ...cote client:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    if (message.equals("UNIVER")) {
    					client.setAvancement(10 ,"Loading Univer...",3);
    					log.info("Loading Univer...");
    					//recuperation de l'univers
    					  InputStream is = socketLocal.getInputStream();
    					  client.setAvancement(10 ,"Loading Univer...",3);
    					  ObjectInputStream ois = new ObjectInputStream(is);
    					  client.setAvancement(10 ,"Loading Univer...",3);
    					 try {
    						log.info("Univer Object incomming...");
     
    						Univers mainUniver=(Univers) ois.readObject();
    						client.setAvancement(50 ,"Loading Univer...",3);
    						System.out.println(mainUniver.getName());
     
    						client.setClientEnable();
    					} catch (ClassNotFoundException e) {
    						e.printStackTrace();
    					}
    					log.info("Reday to play");
    					client.setClientEnable();	
    				}
    c'est la partie ou le client comprend quil va recuperer l'objet, tout est ok, les messages de logs sont correcte sauf que l'exception se produit sur: ObjectInputStream ois = new ObjectInputStream(is); alors que je n'ai pas encors commencer a lire l'objet recu.

    Voila si vous voulez d'autres infos pas de soucis je suis la. et merci =)
    ps:desole pour les 'a' sans accents mais pas moyen de les faire avec un clavier allemand sous linux
    ps2:je viens de decouvrir que univers prenait un 's' donc ne faites pas attention je vais corriger ca de suite =)

  5. #5
    Membre expérimenté Avatar de hydraland
    Profil pro
    Développeur Java
    Inscrit en
    Mai 2006
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mai 2006
    Messages : 179
    Par défaut
    Salut,

    Je pense que le problème vient du fait que tu clôs ta socket coté serveur avant que le client ai terminé de lire les données qu'elle contient. Il faudrait que ton serveur clôt la connexion quand le client à tous lu. Par exemple le client pourrait envoyer un message au serveur lui indiquant qu'il a terminé de lire les données, le serveur pouvant ainsi clôre la connexion.

    A+
    Hydraland

  6. #6
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut uhm
    En faite mon serveur ne clos jamais la connection, enfin pas comme cela, il y a que quelques possibilitees pour fermer son socket vers le client:

    - le client n'a pas le bon mot de passe pour acceder au serveur (ca c'est une mini-securitee pour eviter qu'un programmeur ne vienne spamer le serveur sur son port), comme cela direct la connection vers le client est coupee.
    - le client n'a pas une version compatible avec le serveur.
    - une erreur c'est produite chez le client et c'est le client lui meme qui a coupe la connection, c'est ce qui arrive ici.

    dans le cas ou je ne trouverai pas de solution il me reste la possibilitee d'envoyer le fichier tels qu'il est sur le serveur et de le deserialiser chez le client. On pourra appeler ca ma roue de secours

    Je viens de faire deux tests:
    - le ping n'est pas encors active a cette etape du programme donc il ne peut pas gener le flux en sortie
    - jai fais appel a une methode de l'objet tout juste deserialise sur le serveur et la methode fonctionne, donc le transfert comme vous le dites doit effectivement etre incomplet ou errone.

    merci,

  7. #7
    Membre expérimenté Avatar de hydraland
    Profil pro
    Développeur Java
    Inscrit en
    Mai 2006
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mai 2006
    Messages : 179
    Par défaut
    Citation Envoyé par Yan17
    En faite mon serveur ne clos jamais la connection, enfin pas comme cela, il y a que quelques possibilitees pour fermer son socket vers le client:
    Si j'ai bien compris la méthode
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    serviceSocket.getOutputStream()
    te renvoi le flux de sortie de la socket. Donc le code fait quoi à ton avis???

    A+
    Hydraland

  8. #8
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut uhm...
    Oui en effet tu avais raison la bonne nouvelle c'est que cela semble marcher, il y a un leger temps d'attente,
    malheureusement j'ai une nouvelle exception:

    java.io.StreamCorruptedException: invalid stream header: 50494E47
    at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:783)
    at java.io.ObjectInputStream.<init>(ObjectInputStream.java:280)
    at main.support.network.ServerQuery.run(ServerQuery.java:110)

    elle se produit toujours sur le ObjectOutputStream:
    ObjectInputStream ois = new ObjectInputStream(is);

    je viens de faire des recherches, je precise juste que toutes les classes serialisables de mon programme ont bien un static id et que les version sur le serveur et le client sont les memes.

  9. #9
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut ouf!
    Je viens de voir quelque chose.

    Le serveur transmet l'objet tres rapidement mais le client lui met beaucoup trop de temps a recuperer l'objet, ce qui engendre le timeout du serveur et grace au log4j qui affiche les log aux centieme de secondes pret on peut voir que l'exception se produit car le seveur a deconnete le client donc que l'objet n'etait pas totalement charge chez le client. Je continue de chercher...

  10. #10
    Membre expérimenté Avatar de hydraland
    Profil pro
    Développeur Java
    Inscrit en
    Mai 2006
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mai 2006
    Messages : 179
    Par défaut
    Peut tu nous montrer le code du client qui se trouve avant la ligne
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (message.equals("UNIVER")) {
    A+
    Hydraland

  11. #11
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut code code...
    Voila le partie du client:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    while(socketLocal.isConnected()){
     
    		try {
    			message=fluxEntree.readLine();
    			if (message!=null) { 
    				if (message.equals("SERVER_PASSWORD")) {
    					client.setAvancement(20 ,"Set server password",1);
    					log.info("Server ask for id");
    					fluxSortie.println(PropertiesManager.getExpansionKey("server_pwd"));
    				}
    				if (message.equals("WRONG_SERVER_PASSWORD")) {
    					client.setAvancement(10 ,LanguageManager.getAnInternationalizeString("faux_pwd"),1);
    					log.info("The server password is wrong");
    					client.setClientDisable();	
    				}
    				if (message.equals("WRONG_CLIENT_VERSION")) {
    					client.setAvancement(20 ,"Your client version is not supported",1);
    					log.info("The client version is not supported");
    					client.setClientDisable();	
    				}
    				if (message.equals("CLIENT_VERSION")) {
    					client.setAvancement(20 ,"Set client version",1);
    					log.info("Server ask for version");
    					fluxSortie.println("0.1");
    				}
    				if (message.equals("PING")) {
    					log.info("Server ping me");
    					fluxSortie.println("PONG");
    				}
    				if (message.equals("LOGIN")) {
    					fluxSortie.println(PropertiesManager.getExpansionKey("login")+":"+PropertiesManager.getExpansionKey("login_pwd")+":"+PropertiesManager.getExpansionKey("univer"));
    					client.setAvancement(0 ,"OK!",1);
    					client.setAvancement(50 ,"Send login/password",2);
    					log.info("Server ask for login");
    				}
    				if (message.equals("OK")) {
    					client.setAvancement(50 ,LanguageManager.getAnInternationalizeString("bienvenue"),2);
    					log.info("ok, waiting for univer...");	
    				}
    				if (message.equals("WRONG_PASSWORD")) {
    					client.setAvancement(40 ,LanguageManager.getAnInternationalizeString("faux_pwd"),2);
    					log.info("The login password is wrong");
    					client.setClientDisable();	
    				}
    				if (message.equals("WRONG_UNIVERS")) {
    					client.setAvancement(40 ,LanguageManager.getAnInternationalizeString("faux_univers"),2);
    					log.info("The univers is wrong");
    					client.setClientDisable();	
    				}
    				if (message.equals("NULL")) {
    					client.setAvancement(0 ,"Login/password can not be null",2);
    					log.info("The login/password is null");
    					client.setClientDisable();	
    				}
    				if (message.equals("UNIVERS")) {
    					client.setAvancement(10 ,"Loading Univers...",3);
    					log.info("Loading Univers...");
    					//recuperation de l'univers
     
    					  InputStream is = socketLocal.getInputStream();
     
    					  client.setAvancement(10 ,"Loading Univers...",3);
    					  ObjectInputStream ois = new ObjectInputStream(is);
    					  //BufferedInputStream fis=new BufferedInputStream(is);
    					  client.setAvancement(10 ,"Loading Univers...",3);
    					 try {
    						log.info("Univers Object incomming...");
     
    						Object temp= ois.readObject();
    						//Object temp=((ObjectInput) fis).readObject();
    						client.setAvancement(50 ,"Loading Univers...",3);
     
    						client.setClientEnable();
     
    						Univers mainUniver=(Univers) temp;
    						System.out.println(mainUniver.getName());
    					} catch (ClassNotFoundException e) {
    						e.printStackTrace();
    					}
     
    					log.info("Reday to play");
    					client.setClientEnable();	
    				}
     
    				message="";
    			}
    		} catch (IOException e) {
    			e.printStackTrace();
    			log.error("Error between Client and Server");
    			log.info("Deconnected from server");
    			client.setClientDisable();
    			return;
     
    		}
    commentaires:
    le setClientEnable et le setClient disable servent a activer ou desactiver l'interface graphique, mais dans la methode setClientDisable il y a aussi un socket.close() , celui du client.

    setAvancement c'est pour un JProgressBar, le premier chiffre indique la valeur a ajouter dans la JProgressBar, le string au milieu c'est pour indiquer dans un JLabel et le dernier chiffre indique quelque JProgress bar est consernee car il y a 3 JProgressBar.

    Le propertiesManager renvoie des valeurs issue dun fichier en dehors du programme, le language manager gere la traduction, dans cette partie du programme c'est pas encors comple car je veux surtout que cela fonctionne avant de traduire.

    en esperant que ca peut aider merci

  12. #12
    Membre expérimenté Avatar de hydraland
    Profil pro
    Développeur Java
    Inscrit en
    Mai 2006
    Messages
    179
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Développeur Java

    Informations forums :
    Inscription : Mai 2006
    Messages : 179
    Par défaut
    Comment est initialisé la variable fluxEntree. Mon hypothèse c'est que tu utilises deux types de flux différents pour lire ta socket et que cela génère un conflit entre eux.
    EX :
    Tu utilises un flux A pour lire une donnée. Le problème c'est qu'il te lit ta donnée ainsi que la suite.
    Tu utilise un flux B pour lire la donnée suivante. Le problème c'est que le flux A à déjà lu en partie les octets de la donnée suivante, donc ton flux B plante.

    A+
    Hydraland

  13. #13
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut peu etre..
    Desole de ne pas repondre plus tot mais je n'ai pas internet chez moi donc je ne peut poster que ce matin.

    Jai une bonne nouvelle, apres avoir detruit une class qui apparemment genee la seriaisation, le procede d'echange entre serveur client, fonctionne bien, sauf que il fonctionne mais par intermitence, en gros il ne fonctionne pas tout le temps.

    Je vais faire comme Hydraland a dit, je vais voir si en ne creeant qu'un seul flux d' entree cela fonctionne, car en effet j'en ai deux la.

    je vais tester ca , merci

    Sinon vive la serialisation c'est trop bien ce truc!!

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    15
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 15
    Par défaut ouf!
    Me revoila,

    je voulais annoncer le succes total de l'idee de Hydraland grand merci, en gros j'avais plusieurs flux que ce soit entrants ou sortants du cote client et meme serveur , donc on peut suposer que parfois certaines donnees etaient manger par les autres.

    Donc je ne travail desorme plus que avec des flux d'objets et non plus de BufferedStream ou Printstream, l'avantage est que c'est beaucoup plus sur desorme au transfert par contre..........cela alourdit considerableemnt le code avec tout les try catch a ajouter.

    mais bon c'est cool ca marche! encors merci

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Transfert d'objet via sockets
    Par benjamin-mermoz dans le forum Windows Forms
    Réponses: 5
    Dernier message: 11/12/2008, 22h34
  2. deserialisation d'objet envoyé par socket
    Par rhifay dans le forum Entrée/Sortie
    Réponses: 7
    Dernier message: 27/09/2008, 15h12
  3. Réponses: 4
    Dernier message: 04/06/2008, 23h56
  4. Réponses: 17
    Dernier message: 15/05/2007, 19h35
  5. Transfert d'une image par socket stream
    Par francky23012301 dans le forum Langage
    Réponses: 1
    Dernier message: 31/10/2005, 17h06

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo