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 :

[Socket] optimiser les paramètres de connexion


Sujet :

Entrée/Sortie Java

  1. #1
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut [Socket] accélerer le débit
    bonjour,

    j'ouvre un port puis j'envoie un tableau sur ce port. Tout se passe bien je reçois exactement ce que je veux. Le problème est que la durée d'envoi des données est trop longue. Elle est de 300ms. On m'impose d'envoyer ces données en moins de 30ms.

    Comment je peux accélérer le débit ? J'utilise un DataOuptuStream pour envoyer mon tableau :

    Voici mon code : (j'ai volontairement enlevé les try{}catch{})
    Le code après la méthode accept dure 300ms.
    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
     
    socketServerSender=new ServerSocket(4000);
     
    socketServerSender.setSoTimeout(2000);
    socketSender=this.socketServerSender.accept();
     
     
    out=socketSender.getOutputStream();
    dos=new DataOutputStream(out);
     
    dos.writeInt(255);
    dos.flush();
    out.flush();
     
    int n, m, o;
    int i, j, k;
    n = tabInt.length;		//9(objets)
    m = tabInt[0].length;	//50(lignes)
    o = tabInt[0][0].length;	//20(colonnes)
     
     
    for (i=0;i<n;i++)
    {
    	for (j=0;j<m;j++)
    	{
    		for (k=0;k<o;k++)
    		{
    			dos.writeInt(tabInt[i][j][k]);
    		}
    	}
    }
     
    dos.flush();
    out.flush();
    J'ai essayé de remplacer mon tableau 3D par un tableau 1D, même chose j'ai un temps d'envoi de 300ms environ.


    [edit]
    Petite précision :
    ce code se trouve dans un thread. Est-ce que ça peut expliquer la lenteur d'exécution ?
    [/edit]

  2. #2
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    D'abord, comment vérifies-tu les 30ms ?

    Ensuite, je suis un peu étonné que tu utilises un DataOutpurStream, un flux assez évolué, qui fait des traitements sur les données, risque de perte de temps j'imagine ; pourquoi n'utilises-tu pas un BufferedOutputStream, ou même directement l'OutputStream de la socket ?

    Ensuite, peut être aussi examiner les possibilités de nio, mais j'ai jamais su si c'était vraiment plus rapide, en tous cas c'est prévu pour.

  3. #3
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Citation Envoyé par gifffftane Voir le message
    D'abord, comment vérifies-tu les 30ms ?
    sur le programme client. Je mesure le temps avant et après exécution du programme.

    Petite remarque importante : le programme client n'est pas en Java mais en matlab (la fonction pnet pour être précis).

    Citation Envoyé par gifffftane Voir le message
    Ensuite, je suis un peu étonné que tu utilises un DataOutpurStream, un flux assez évolué, qui fait des traitements sur les données, risque de perte de temps j'imagine ; pourquoi n'utilises-tu pas un BufferedOutputStream, ou même directement l'OutputStream de la socket ?
    Disons que j'ai pris le DataOutputStream car c'est à ma connaissance le seul objet capable d'envoyer des int32.
    Quant au BufferedOutputStream j'avoue que je ne sais pas vraiment m'en servir J'ai essayé d'envoyer des informations via cet objet je recueillais n'importe quoi à l'arrivée (sans doute parce j'ai dû mal configurer pnet).

    Citation Envoyé par gifffftane Voir le message
    Ensuite, peut être aussi examiner les possibilités de nio, mais j'ai jamais su si c'était vraiment plus rapide, en tous cas c'est prévu pour.
    tu penses au IntBuffer ? Mais je ne vois pas comment l'associer au OutputStream de mon socket

  4. #4
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Citation Envoyé par Auteur Voir le message
    sur le programme client. Je mesure le temps avant et après exécution du programme.

    Petite remarque importante : le programme client n'est pas en Java mais en matlab (la fonction pnet pour être précis).
    Donc à ce que je comprends de la doc, le temps compté est non seulement celui du transfert, mais de plus il y a dedans le temps d'ouverture de la connexion socket, non ?

  5. #5
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Citation Envoyé par gifffftane Voir le message
    Donc à ce que je comprends de la doc, le temps compté est non seulement celui du transfert, mais de plus il y a dedans le temps d'ouverture de la connexion socket, non ?
    Tout à fait.

    Du côté matlab : j'ouvre le port, je reçois les données puis je ferme le port. Pour ce programme Matlab, je n'ai pas le choix, je dois procéder ainsi. Donc du côté Java je dois me plier à cette contrainte.

    Du côté Java : j'attends l'ouverture du port, dès qu'il est ouvert j'envoie mes données. Donc en Java, je suis obligé de faire un thread dans lequel je mets une boucle avec la méthode accept(). Dès que la connexion est établie, un flag passe à true, je sors de la boucle et j'envoie les données.


    Quand je vois mon programme Java, je constate qu'il n'est pas très optimisé :red: :red:

  6. #6
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Pour en revenir à nio, tu as un exemple de serveur dans la doc du jdk à NIO Examples :TimeServer renvoie l'heure - ce n'est pas très différent de tes entiers je suppose - de façon nio-teligente.

  7. #7
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Je crois que je vais devoir passer par un SocketChannel pour aller plus vite.

    La plupart des exemples trouvés sur le net utilisent des PrintWriter pour écrire les données via la méthode print(). Seul souci est que les informations envoyées sont converties en code ASCII (même les nombres).

    Reste à trouver côté matlab la bonne configuration pour réceptionner le flux


    Au fait si je passe par un SocketChannel pour envoyer mes données est-ce que je dois le configurer comme bloquant ou non bloquant ? Sur ce point je n'ai pas très bien compris la différence entre bloquant et non bloquant.

    Penses-tu que je peux améliorer le débit en modifiant les paramètres de connexion de mon socket ? Je pensais à la méthode setTrafficClass et fermer le flux d'entrée (shutdownInput) car par ce port je ne reçois aucune donnée.

  8. #8
    Membre Expert
    Avatar de gifffftane
    Profil pro
    Inscrit en
    Février 2007
    Messages
    2 354
    Détails du profil
    Informations personnelles :
    Localisation : France, Loire (Rhône Alpes)

    Informations forums :
    Inscription : Février 2007
    Messages : 2 354
    Par défaut
    Malheureusement je ne peux pas beaucoup t'aider sur la partie optimisation des paramètres de connexion. Pose une autre question sur ce point précis, et peut être auras-tu plus de chance.

    Concernant nio vs io, vérifie bien avant de t'embarquer que tu obtiens bien de meilleurs résultats sur une maquette basée sur nio.

  9. #9
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut [Socket] optimiser les paramètres de connexion
    bonjour,

    j'ouvre un port de cette manière :
    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
    socketServerSender=new ServerSocket(4000);
     
    socketServerSender.setSoTimeout(2000);
    socketSender=this.socketServerSender.accept();
     
    // envoi des données
    out=socketSender.getOutputStream();
    dos=new DataOutputStream(out);
     
    dos.writeInt(255);
    dos.flush();
    out.flush();
     
    int n, m, o;
    int i, j, k;
    n = tabInt.length;		//9(objets)
    m = tabInt[0].length;	//50(lignes)
    o = tabInt[0][0].length;	//20(colonnes)
     
     
    for (i=0;i<n;i++)
    {
    	for (j=0;j<m;j++)
    	{
    		for (k=0;k<o;k++)
    		{
    			dos.writeInt(tabInt[i][j][k]);
    		}
    	}
    }
     
    dos.flush();
    out.flush();
     
    //.... etc.

    Mon souci est que le débit est un peu lent : 300ms pour tout envoyer. Je voudrais envoyer les données en 30ms. De plus la méthode accept étant bloquante, je suis obligé de placer ce code dans un thread.

    Les 300ms sont mesurés sur le poste client : le programme client ouvre le port, reçoit les données, puis ferme le port.

    Mais visiblement un DataOuputStream n'est pas l'idéal pour ça il faudrait que j'utilise l'API nio plutôt que io.


    A priori il faudrait que je passe par un SocketChannel pour envoyer mes données plus rapidement. Du coup je me demande :
    • est-ce que je dois le configurer comme bloquant ou non bloquant ? Sur ce point je n'ai pas très bien compris la différence entre bloquant et non bloquant.
    • est-ce je peux améliorer le débit en modifiant les paramètres de connexion de mon socket ? Je pensais à la méthode setTrafficClass et fermer le flux d'entrée (shutdownInput) car par ce port je ne reçois aucune donnée.

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    T'as essayé de passer par un BufferedOutputStream ?

  11. #11
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Oui, mais les données reçues sont visiblement mal interprétées par le programme client. Sans douter une mauvaise configuration du programme client... Donc je réessayerai.


    En fait, j'avais choisi le DataOuputStream car je peux envoyer directement des entiers 32 bits, tandis que les autre types d'objets (comme le BufferedOutputStream) n'envoient que des Bytes ou des Char.
    Ce qui pose quelques soucis pour réceptionner les données (le programme client est sous Matlab, pas en java).


    Pour le BufferedOutputStream tu peux me donner un exemple d'utilisation ? Comment ferais-tu pour envoyer des entiers 32 bits en utilisant un tableau de Bytes (car visiblement le BufferedOutputStream ne gère que ce format) ?

  12. #12
    Membre Expert
    Profil pro
    Inscrit en
    Août 2006
    Messages
    3 276
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2006
    Messages : 3 276
    Par défaut
    Ben d'après la Javadoc, le BufferedOutputStream a les méthodes:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    write(byte[] b, int off, int len)
    Writes len bytes from the specified byte array starting at offset off to this buffered output stream.
    Writes the specified byte to this buffered output stream.

    Il suffit d'encapsuler ton DataOutputStream dans le BufferedOutputStream.

    A tester.

  13. #13
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    Citation Envoyé par fr1man Voir le message

    Il suffit d'encapsuler ton DataOutputStream dans le BufferedOutputStream.
    Certains concepts m'échappent encore en Java. Peux-tu me dire comment tu ferais ? Pour moi les types sont incompatibles....


    Tu ne sais pas si en jouant sur ces paramètres de connexion je peux améliorer la vitesse de transfert des données (cf. mon 1er message) ?

  14. #14
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,


    J'ai fusionné les discussions : inutile d'éparpiller les infos si tu veux une réponse


    L'encapsulation permet englober plusieurs type de flux différents pour profiter des avantages de chacun :
    • Le DataOutputStream permet d'écrit des types de données tels quel (entiers sur 32 bits, etc...).
    • Le BufferedOutputStream utilise un buffer pour écrire les données, puis copiera ces données sur le flux par la suite pour minimiser le nombre d'appel d'entré/sortie et donc améliorer les performances.


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DataOutputStream out = new DataOutputStream( new BufferedOutputStream( socketSender.getOutputStream() ) );
    Sans oublier les try/finally pour la libération...

    a++

  15. #15
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    adiGuba

    Excellent, génial

    Merci à vous. Là grâce au buffer, j'envoie mes données en.... 8ms au mieux, 20ms au pire
    Ça répond parfaitement au cahier des charges

    Je vais juste rajouter une remarque :
    il faut faire le flush() sur le BufferedOutputStream pas sur le DataOutputStream ou le OutputStream du socket
    Sinon là on a à nouveau des temps de transmission très long (~300ms)

  16. #16
    Expert confirmé
    Avatar de Auteur
    Profil pro
    Inscrit en
    Avril 2004
    Messages
    7 660
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2004
    Messages : 7 660
    Par défaut
    D'ailleurs je ne comprends pas pourquoi la durée de la transmission avec le buffer varie comme ça du simple au double : entre 8ms et 20ms ? Je m'attendais à quelque chose de plus constant...

    Est-ce le fait que la fonction soit dans un thread ?

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 01/12/2008, 09h57
  2. Externaliser les paramètres de connexion à la base ?
    Par Bobsinglar dans le forum Struts 2
    Réponses: 4
    Dernier message: 30/11/2007, 11h03
  3. [D7 - ADO]Tester les paramètres de connexion
    Par portu dans le forum Bases de données
    Réponses: 3
    Dernier message: 17/04/2007, 19h29
  4. Optimiser les paramètres MySQL - appel aux experts
    Par SuperCed dans le forum SQL Procédural
    Réponses: 4
    Dernier message: 04/12/2006, 12h26
  5. Cacher les paramètres de connexion à la BD
    Par Invité dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 12/10/2006, 17h04

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