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

Tomcat et TomEE Java Discussion :

Tomcat peut-il être Serveur de sockets non HTTP ?


Sujet :

Tomcat et TomEE Java

  1. #1
    Membre à l'essai
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Points : 15
    Points
    15
    Par défaut Tomcat peut-il être Serveur de sockets non HTTP ?
    Bonjour,

    Peut être que le titre pourrait être changé, je ne vois pas trop comment faire ...

    Voilà le besoin :

    J'ai un Tomcat en fonction sur un serveur. Il délivre une application Web
    sur le port 8080.

    J'ai un client qui souhaite envoyer des informations que j'aimerais prendre en compte pour exécuter des traitements dans Tomcat. Comme je ne sais pas quand ce client m'envoie des infos, Tomcat doit être à l'écoute permanente. De plus, lorsqu'un train de données arrivées a été correctement traité par Tomcat, j'aimerais renvoyer une confirmation à mon client qui, entre temps, se serait mis en pause , pour parfaire le tableau, on ne connaît pas non plus la taille des données envoyées ! !

    Voilà où j'en suis

    J'ai d'abord pensé à des sockets .... mais je sèche ... je ne sais pas si c'est faisable ou pas ... mon client peut-il m'envoyer des données brutes ( sans encapsuler ça dans du HTTP ? ) Y a -t-il moyen ? une modif dans server.xml ?
    un servlet .... mais bon je vois pas trop, les seules choses que j'ai trouvées font référence à des sockets entre applets et tomcat
    http://litis.univ-lehavre.fr/~colett...ervlet/10.html
    http://bruce-eckel.developpez.com/li...chap=16&page=1
    http://manu.e3b.org/Java/Tutoriels/P...au/Sockets.htm

    ou alors je demande au client de m'envoyer les données dans un format particulier ... vers l'adresse du genre http:adresse_ip:8080/MonServletCible et je fais le traitement là, mais alors n'y aura-t-il pas des pbs du fait que je ne connaisse ni la taille des données ( ce sont des données CRUD je dois tout avoir pour ensuite débuter une transaction dans la BdD ). Et dans ce cas n'y a-t-il pas un pb puisque mon client n'est pas un client web ?

    Bref voili voilou je sèche sur la façon de m'y prendre....

  2. #2
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut
    Un peu de théorie avant de ce perdre...
    Tomcat est un conteneur. Il contient des servlets... entre autre. Il est fait pour fonctionner en relation client/serveur Web : le serveur (Tomcat) est à l'écoute, un client demande une connexion, puis soumet un requête. Le serveur traite la requête. Une fois le traitement terminé, le serveur -peut- retourner une réponse au client. La connexion est fermé -depuis HTTP 1.1 c'est plus forcement le cas avec Connexion-keepAlive.

    C'est le cas de l'HTML, les services Web etc. Le serveur ne peut en aucun cas initier la connexion avec le client. Le développement des concepts Ajax à permis de 'cacher' ce manque, en effectuant des requêtes cachées au serveur, et rendu sur la page HTML du navigateur.

    On s'adapte à ton cas...
    Partant du faite que Tomcat répond à une demande, le lancement de la demande peut être fait via une connexion HTTP -GET ou POST- avec la nature du traitement (servlet) et les paramètres pour leur execution. Lorsque le traitement est trop long, le mieux et de faire un thread qui execute le traitement. Le client reçoit alors une page l'informant que le traitement est en cours. Le rafaîchissement automatique peut être utilisé (ou un lien de "refresh") toutes les 5 secondes par exemple. Le rafraîchissement demande l'état du thread de traitement. S'il a fini, le résultat est retourné. Sinon, il informe à nouveau du traitement en cours.

    Après, le client Web peut ne pas vouloir attendre... Là, le client ferme la connexion avant la fin du traitement, et tu ne sais plus où envoyer la réponse -le socket de retour n'existe plus et tu obtiens une exception. Dans ce cas, le mieux et de placer un attribut d'application, pointant sur le thread de traitement (l'objet thread du moins). Le traitement génére les fichiers résultants dans un répertoire temporaire. Si le client se connect plus tard pour un traitement ou voir l'évolution du traitement, la servlet regarde dans les attributs d'application si le traitement et en cours ou fini. suivant le cas, il retourne l'informations ou les informations.

    J'ai implémenté cela pour un client, avec retour par courriel -au connecté ayant demandé le traitement- des traitements, et logs. Certains traitements durent 6 heures. Cela fonctionne très bien... Il ya même une page de gestion qui a été crée pour manager les historiques, les logs, les threads en cours etc.

    Une solution "light" peut être possible.

  3. #3
    Membre à l'essai
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Points : 15
    Points
    15
    Par défaut Merci Lorantus
    Merci beaucoup Lorantus pour ta réponse argumentée et illustrée. Elle m'aide vraiment beaucoup. Je me dirige donc vers les concepts que tu as abordés. La partie théorie est toujours la bienvenue ! Lol Merci encore, je posterai probablement à nouveau sur ce fil en cas de Pb mais je ne suis déjà plus dans le noir

  4. #4
    Membre à l'essai
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Points : 15
    Points
    15
    Par défaut Bon alors là j'ai besoin d'un prof !! ;-) ...
    Bon ben non j'y arrive pas A mon avis c'est pourtant un besoin qui doit revenir souvent mais je ne trouve pas la solution à ce problème. J'ai bien des débuts de réponses, des exemples etc. mais aucun ne me semble convenir ... Je dois très probablement passer à côté et comme je sèche je reste fixé. Il faudrait un regard externe


    Mon but :


    A l'aide d'un petit prog en langage C, envoyer depuis une machine vers un servlet de mon Tomcat abrité par une autre machine les lignes suivantes :

    Pour DaemonHttpServlet
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    Ligne 1
    Ligne 2
    Grande Liiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiigne 3
    Ligne 4
    Sur internet, j'ai trouvé des référence à DaemonHttpServlet qui, semble-t-il devrait être correct pour faire ça .... mais c'est le HTTP qui m'ennuie ?!?! ou alors c'est juste pour l'initialisation ? mais alors où on récupère le socket ?!?! Pff là je mange mes chaussures !

    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
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
     
    // Copyright (C) 1998 by Jason Hunter <jhunter@acm.org>.  All rights reserved.
    // Use of this class is limited.  Please see the LICENSE for more information.
     
    package maj;
     
    import java.io.*;
    import java.net.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
     
    /** 
     * A superclass for HTTP servlets that wish to accept raw socket 
     * connections.  DaemonHttpServlet 
     * starts listening for client requests in its <tt>init()</tt> method 
     * and stops listening in its <tt>destroy()</tt> method.  In between, 
     * for every connection it receives, it calls the abstract 
     * <tt>handleClient(Socket client)</tt> method.  This method should 
     * be implemented by the servlet subclassing DaemonHttpServlet.
     * The port on which the servlet is to listen is determined by the 
     * <tt>getSocketPort()</tt> method.
     *
     * @see com.oreilly.servlet.RemoteDaemonHttpServlet
     *
     * @author <b>Jason Hunter</b>, Copyright © 1998
     * @version 1.0, 98/09/18
     */
    public abstract class DaemonHttpServlet extends HttpServlet {
     
      /**
       * The default listening port (1313)
       */
      protected int DEFAULT_PORT = 1313;
      private Thread daemonThread;
     
      /**
       * Begins a thread listening for socket connections.  Subclasses
       * that override this method must be sure to first call 
       * <tt>super.init(config)</tt>.
       * 
       * @param config the servlet config
       * @exception ServletException if a servlet exception occurs
       */
        @Override
      public void init(ServletConfig config) throws ServletException {
        super.init(config);
     
        try {
          daemonThread = new Daemon(this);
          daemonThread.start();
        }
        catch (Exception e) {
          log("Problem starting socket server daemon thread" +
              e.getClass().getName() + ": " + e.getMessage());
        }
      }
     
      /**
       * Returns the socket port on which the servlet will listen.
       * A servlet can change the port in three ways: by using the 
       * <tt>socketPort</tt> init parameter, by setting the <tt>DEFAULT_PORT</tt>
       * variable before calling <tt>super.init()</tt>, or by overriding this 
       * method's implementation.
       *
       * @return the port number on which to listen
       */
      protected int getSocketPort() {
        try { return Integer.parseInt(getInitParameter("socketPort")); }
        catch (NumberFormatException e) { return DEFAULT_PORT; }
      }
     
      /**
       * Handles a new socket connection.  Subclasses must define this method.
       *
       * @param client the client socket
       */
      abstract public void handleClient(Socket client);
     
      /**
       * Halts the thread listening for socket connections.  Subclasses
       * that override this method must be sure to first call 
       * <tt>super.destroy()</tt>.
       */
     
        @Override
      public void destroy() {
        try {
          daemonThread.stop();
          daemonThread = null;
        }
        catch (Exception e) {
          log("Problem stopping server socket daemon thread: " +
              e.getClass().getName() + ": " + e.getMessage());
        }
      }
    }
     
    // This work is broken into a helper class so that subclasses of
    // DaemonHttpServlet can define their own run() method without problems.
     
    class Daemon extends Thread {
     
      private ServerSocket serverSocket;
      private DaemonHttpServlet servlet;
     
      public Daemon(DaemonHttpServlet servlet) {
        this.servlet = servlet;
      }
     
        @Override
      public void run() {
        try {
          // Create a server socket to accept connections
          serverSocket = new ServerSocket(servlet.getSocketPort());
        }
        catch (Exception e) {
          servlet.log("Problem establishing server socket: " +
                      e.getClass().getName() + ": " + e.getMessage());
          return;
        }
     
        try {
          while (true) {
            // As each connection comes in, call the servlet's handleClient().
            // Note this method is blocking.  It's the servlet's responsibility
            // to spawn a handler thread for long-running connections.
            try {
              servlet.handleClient(serverSocket.accept());
            }
            catch (IOException ioe) {
              servlet.log("Problem accepting client's socket connection: " +
                          ioe.getClass().getName() + ": " + ioe.getMessage());
            }
          }
        }
        catch (ThreadDeath e) {
          // When the thread is killed, close the server socket
          try {
            serverSocket.close();
          }
          catch (IOException ioe) {
            servlet.log("Problem closing server socket: " +
                        ioe.getClass().getName() + ": " + ioe.getMessage());
          }
        }
      }
    }
    Pour DaytimeServlet4

    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
     
    package maj;
     
    import java.io.*;
    import java.util.*;
    import javax.servlet.*;
    import javax.servlet.http.*;
    import java.net.*;
     
    public class DaytimeServlet4 extends DaemonHttpServlet {
     
      public Date getDate() { return new Date(); }
     
     
      public void init() throws ServletException {
        super.init();
      }
     
        @Override
      public void doGet(HttpServletRequest req, HttpServletResponse res)
                                   throws ServletException, IOException {
    	if("object".equals(req.getParameter("format"))){
    		ObjectOutputStream out = new ObjectOutputStream(res.getOutputStream());
    		out.writeObject(getDate());
    	}else {
          		PrintWriter out = res.getWriter();
          		out.println(getDate().toString());
    	}
      }
     
        @Override
      public void doPost(HttpServletRequest req, HttpServletResponse res)
                                    throws ServletException, IOException {
        doGet(req, res);
      }
     
     
        @Override
     public void destroy() { super.destroy(); }
     
     
      public void handleClient(Socket client) {
        new DaytimeConnection(this, client).start();
      }
    }
     
    class DaytimeConnection extends Thread {
     
      DaytimeServlet4 servlet;
      Socket client;
     
      DaytimeConnection(DaytimeServlet4 servlet, Socket client) {
        this.servlet = servlet;
        this.client = client;
        setPriority(NORM_PRIORITY - 1);
      }
     
        public void run() {
        try {
          DataInputStream in = new DataInputStream(
                               new BufferedInputStream(
                               client.getInputStream()));
          String line = in.readLine();
     
          if ("object".equals(line)) {
            ObjectOutputStream out = new ObjectOutputStream(client.getOutputStream());
            out.writeObject(servlet.getDate());
            out.close();
          } else {
            PrintStream out = new PrintStream(client.getOutputStream());
            out.println(servlet.getDate().toString());
            out.close();
          }
          client.close();
        }
        catch (IOException e) {
          servlet.getServletContext().log(e, "IOException while handling client request");
        }
        catch (Exception e) {
          servlet.getServletContext().log("Exception while handling client request");
        }
      }
    }
    Alors oui mon servlet est en démarrage auto au lancement du serveur donc, si je comprends, il ecoute sur le port 1313 par défaut ?!?! Là c'est déjà très moyen ....

    Besoin d'un professeur

  5. #5
    Membre éclairé Avatar de Lorantus
    Homme Profil pro
    Consultant développeur indépendant / Java/VB/C(++)/ObjectPal
    Inscrit en
    Août 2007
    Messages
    599
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : France, Haute Savoie (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant développeur indépendant / Java/VB/C(++)/ObjectPal

    Informations forums :
    Inscription : Août 2007
    Messages : 599
    Points : 882
    Points
    882
    Par défaut
    Il est pas mal ton petit servlet... deamon... il me plait bien...

    Il semble bien qu'il écoute le port 1313... il pourra pas écouter le 80 (HTTP) car il devrait être pris par le Tomcat -port 80: port HTTP.

    Par contre, il faut implementer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public void handleClient(Socket client)
    et tout faire la dedans. Je vois pas trop pourquoi tu as doGet et doPost...

    L'ensemble est quand même complexe... regarde ici section "Workaround for timeout problem", un exemple de iText, il fait un thread etc... Cela peut te servir de base.

    (J'ai des servlets prêtes à cela aussi, mais elles sont payantes.)

  6. #6
    Membre à l'essai
    Profil pro
    Développeur informatique
    Inscrit en
    Mai 2009
    Messages
    33
    Détails du profil
    Informations personnelles :
    Âge : 52
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique

    Informations forums :
    Inscription : Mai 2009
    Messages : 33
    Points : 15
    Points
    15
    Par défaut
    Je suis d'accord il est pas mal ce servlet .... mais, comme toi, je m'interroge sur le DoGet et DoPost, quand à HandleClient, il est implémenté dans DaytimeServlet4 ....

    Le tout est assez complexe, je ne suis pas sûr que ce soit l'idéal dans mon cas....

    Malheureusement, je manque de temps pour tout creuser correctement alors je garde ça sous le coude gauche et j'y reviendrai plus tard.

    Du coup, je fais ce que je souhaite de manière moins originale puisque mon programme externe m'envoie les données en effectuant une requête Post vers Tomcat qui redirige le tout vers un servlet de traitement

    En tout cas, je reviendrai sur ce pb parce que je n'ai trouvé nulle part réponse à cette question à savoir : Comment faire pour que mon servlet agisse comme ServerSocket à l'écoute permanente sur un port autre que le 8080 qui est le port d'écoute Tomcat ....

Discussions similaires

  1. Serveur esclave peut-il être également serveur de production ?
    Par ctobini dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 19/09/2007, 11h57
  2. Réponses: 2
    Dernier message: 13/06/2007, 11h22
  3. Réponses: 3
    Dernier message: 20/10/2006, 19h50
  4. [GOF] Fabrique abstraite peut-elle être un Singleton ?
    Par manel007 dans le forum Design Patterns
    Réponses: 7
    Dernier message: 06/01/2005, 10h02
  5. Réponses: 6
    Dernier message: 03/09/2003, 10h29

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