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

Android Discussion :

Problème de DefaultHttpClient et/ou Mettre en place un timeout sur un ensemble d'instructions


Sujet :

Android

  1. #1
    Nouveau membre du Club
    Inscrit en
    Avril 2010
    Messages
    48
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 48
    Points : 36
    Points
    36
    Par défaut Problème de DefaultHttpClient et/ou Mettre en place un timeout sur un ensemble d'instructions
    Bonjour,

    Je travaille sur un échange de données client serveur via une application android. A un certain moment, j'envoie une requête avec DefaultHttpClient sur le serveur avec deux parametres String et un cookie d'authentification.

    Une fois sur deux, cette requête ne fonctionne pas. Sauf que je n'ai aucune trace dans les logs. J'ai tout de correct juste avant l'envoi, et je ne reçois pas de réponse. J'ai donc pensé a utiliser les Tiemout pouvant être mis en place avec HttpParams. La encore, le timeout fonctionne pour un web service différent de celui que j'utilise sur le server, mais sur ce web service précis, le timeout ne fonctionne pas et j'attends toujours en vain ma réponse (lorsque la reqête ne marche pas).
    J'ai alors pensé qu'il y avait un problème côté serveur notamment sur ce web service, sauf que je possède une application iPhone qui fait appel à ce meme web service et qui ne présente jamais d'erreur. J'en ai donc déduis que je dois avoir quelque chose de pas normal dans ma connexion.

    A ce point la, déja, je voudrais savoir si quelqu'un pourrait savoir d'ou ça vient ? quel est le problème ?

    Ensuite, loin de moi l'idée de me décourager, et sachant que je ne peux pas modifier le web service côté serveur, j'ai décidé d'implémenter moi-même un timeout fait maison, c'est à dire qu'au bout par exemple de 3 secondes, il passe aux instructions suivantes sans se préoccuper si il a reçu la réponse de la requête. Néanmoins, si entre temps il reçoit la réponse, alors j'annule le timeout et je continue les instructions.

    Quelqu'un aurait-il une idée de comment mettre ce timeout ? j'ai vu les classes Timer et TimerTask mais en lisant leurs docs j'ai l'impression qu'elles ne font pas trop ce que je veux... si quelqu'un a des pistes je suis preneur !!!

    merci d'avance

  2. #2
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    On pourrait voir le bout de code ? (avec setup du timeout des httpparams, envoi de la requête et le truc autour) ?
    Parceque tous les timeouts coté client que j'ai fait ont toujours bien marché ...
    (attention il y a 2 timeouts: un pour la connexion, un pour le transfert des données).
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  3. #3
    Nouveau membre du Club
    Inscrit en
    Avril 2010
    Messages
    48
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 48
    Points : 36
    Points
    36
    Par défaut
    alors ça c'est pour la déclaration de la connexion :

    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
    HttpParams params = new BasicHttpParams();
    		params.setIntParameter(HttpConnectionParams.CONNECTION_TIMEOUT,3000);
    		params.setIntParameter(HttpConnectionParams.SO_TIMEOUT,5000);
    		params.setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);
    		SchemeRegistry schemeRegistry = new SchemeRegistry();
    		schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
    		schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));
    		ThreadSafeClientConnManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
    		client = new DefaultHttpClient(cm, params);
    		// Create a local instance of cookie store
    		CookieStore cookieStore = new BasicCookieStore();
    		// Bind custom cookie store to the local context
    		((AbstractHttpClient) client).setCookieStore(cookieStore);
    		CookieSpecFactory csf = new CookieSpecFactory() {
    			public BrowserCompatSpec newInstance(HttpParams params) {
    				return new BrowserCompatSpec() {
    					@Override
    					public void validate(Cookie cookie, CookieOrigin origin) throws MalformedCookieException {
    						// Oh, I am easy allow all cookies
    					}
    				};
    			}
    		};
    		((AbstractHttpClient) client).getCookieSpecs().register("easy", csf);
    		client.getParams().setParameter(ClientPNames.COOKIE_POLICY, "easy");
     
    		DefaultHttpClient httpclient = new DefaultHttpClient();
    		httpclient.getCookieSpecs().register("easy", csf);
    		httpclient.getParams().setParameter(ClientPNames.COOKIE_POLICY, "easy");
     
    		// Create local HTTP context
    		localContext = new BasicHttpContext();
    		// Bind custom cookie store to the local context
    		localContext.setAttribute(ClientContext.COOKIE_STORE, cookieStore);
    Pour faire un appel au serveur, j'utilise ces instructions :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Map<String, String> params = new HashMap<String, String>();
    		params.put("param1", param1);
    		params.put("param2", param2);
     
    		HttpGet myHttpGet = createGetRequest(String pathWebService, params);
     
    		String response = executeRequest(client, myHttpGet);
    J'utilise donc d'abord la méthode createGetRequest suivante :

    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
    private HttpGet createGetRequest(String service, Map<String, String> params) throws PersonalizedException {
    		StringBuffer url = new StringBuffer(URL_SERVER);
    		url.append(service);
    		if (params != null && params.size() > 0) {
    			for (String pName : params.keySet()) {
    				if (url.indexOf("?") > 0) {
    					url.append("&");
    				} else {
    					url.append("?");
    				}
    				url.append(pName);
    				url.append("=");
    				try {
    					url.append(URLEncoder.encode(params.get(pName), "UTF-8"));
    				} catch (UnsupportedEncodingException e) {
    					throw new PersonalizedException("Local plateform doesn't support UTF-8 encoding");
    				}
    			}
    		}
    		return new HttpGet(url.toString());
    	}
    Ensuite, j'ai une méthode executeRequest qui est :

    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
    private String executeRequest(HttpClient client, HttpUriRequest request) throws PersonalizedException {
    		String result = null;
    		try {
    Log.d("DEBUG","debut");
    			HttpResponse response = client.execute(request, localContext);
    Log.d("DEBUG","fin");
     
    			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
     
    				HttpEntity entity = response.getEntity();
    				BufferedReader reader = new BufferedReader(new InputStreamReader(entity.getContent()));
    				StringBuffer buffer = new StringBuffer();
    				String tmp = null;
    				while ((tmp = reader.readLine()) != null) {
    					buffer.append(tmp);
    				}
    				reader.close();
    				result = buffer.toString();
    			} else {
    				throw new PersonalizedException("HTTP result " + response.getStatusLine().getStatusCode() + "(" + response.getStatusLine().getReasonPhrase() + ")");
    			}
    		} catch (ClientProtocolException e) {
    			e.printStackTrace();
    			throw new PersonalizedException("Protocol exception : " + e.getMessage());
    		} catch (SocketTimeoutException e) {
    			e.printStackTrace();
    			throw new PersonalizedException("Socket exception : " + e.getMessage());
    		} catch (IOException e) {
    			e.printStackTrace();
    			throw new PersonalizedException("Error on connection : " + e.getMessage());
    		}
    		return result;
    	}
    Concrètement, c'est durant l'instruction suivante que ça "plante" :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    HttpResponse response = client.execute(request, localContext);
    Un coup ça va fonctionner et le traitement va s'effectuer normalement, un autre coup ça ne va pas fonctionner, ça va juste attendre la réponse, mais le timeout ne se déclenche pas (dans les logs, j'ai le "début" mais pas le "fin"). Mes paramètres d'envoi sont corrects (que ce soit en GET ou en POST (j'ai une autre méthode pour le POST) j'ai bien l'url de la bonne forme). Au final tout est correct. En réalité, tout laisse à penser que c'est la faute du serveur, mais vu que ça fonctionne sur l'appli iOS, il y a un truc sur android qui fait que ça ne fonctionne pas !

  4. #4
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Le client est fortement customisé....

    Avec un simple DefaultHttpClient() ça donne quoi ?

    On dirait que le client "attend" une connexion libre... Quand ça "timeout" le serveur a bien reçu la requête ? ou toujours pas ?


    Sinon, un truc qui n'a rien à voir avec le problème... mais c'est toujours bon:
    Eviter les "e.printStackTrace();" utiliser "Log.e(TAG,message,e);" à la place. Mais là ce n'est pas la peine vu que l'exception est traduite...
    Du coup dans l'exception "PersonalizedException" rajouter un constructeur avec une "cause" (, Throwable t) et l'utiliser plutôt que de "perdre" l'exception initiale.
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  5. #5
    Nouveau membre du Club
    Inscrit en
    Avril 2010
    Messages
    48
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 48
    Points : 36
    Points
    36
    Par défaut
    Je tiens a préciser que j'ai reçu le code comme ça et que je dois résoudre le problème. Le defautHttpclient customisé, ce n'est pas moi qui l'ai customisé.

    J'ai essayé avec un defautHttpClient simple, mais j'ai besoin de transmettre un cookie qui montre que j'ai été authentifié avant. J'ai donc repris des morceaux de code pour ça mais au final, ça ne fonctionne pas mieux, cela fonctionne pareil qu'avec le client http en ma possession.

    Je n'ai pour l'instant aucuns détails concernant le serveur, sachant qu'il est hébergé "loin" de moi, je dois faire une demande de logs. J'espere les avoir dans les prochains jours. Néanmoins, si vous avez des pistes ou des solutions je suis preneur car ce problème est vraiment préoccupant pour moi. Et j'ai essayé beaucoup de recours...

  6. #6
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    un "cookie" c'est juste un addHeader() sur l'objet HttpGet...
    Mais bon, c'était juste histoire de tester !

    En particulier: params.setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true); me semble vraiment zarb... cela peut créer une boucle infinie dont le get ne revient jamais (puisque jamais de timeout).
    D'où la nécessité d'accéder aux logs.

    Et puisque sur iOS cela fonctionne, c'est forcément un problème "d'environnement" dans le code (HttpParams, Client, ...).

    Essayer aussi avec un CONNECTION_MANAGER_TIMEOUT histoire de...

    Il n'y a vraiment rien dans le logcat ?
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  7. #7
    Nouveau membre du Club
    Inscrit en
    Avril 2010
    Messages
    48
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 48
    Points : 36
    Points
    36
    Par défaut
    Non, il n'y a vraiment rien de rien dans le logcat et pourtant j'ai loggué au maximum.
    J'avais également pensé a supprimer l'instruction : params.setParameter(ClientPNames.ALLOW_CIRCULAR_REDIRECTS, true);

    Je l'ai mis a false, j'ai supprimé la ligne, rien n'y a fait.

    Je tiens a dire également que c'est uniquement sur ce webservice que ça ne fonctionne pas. J'utilise d'autres webservices sur le meme serveur et utilisant le meme client et ça fonctionne très bien.

    Je sais plus trop quoi faire. J'attends les logs du serveur et je reviendrais sur ce topic pour rendre compte de ce qu'il en est. Désespérant, j'm'en arrache les cheveux !

  8. #8
    Nouveau membre du Club
    Inscrit en
    Avril 2010
    Messages
    48
    Détails du profil
    Informations forums :
    Inscription : Avril 2010
    Messages : 48
    Points : 36
    Points
    36
    Par défaut
    Bon, après avoir eu les logs du serveur, il s'avère que le serveur ne recevait pas la requête et donc que ça mouline dans le vide. Il s'agirait donc d'un problème de WAF et de Firewall (dans leur configuration).

    Problème a demi-résolu alors. Des modifications vont être faites.

Discussions similaires

  1. [AC-2000] Mettre en place un contrôle sur une table Access
    Par ceuce dans le forum VBA Access
    Réponses: 9
    Dernier message: 15/09/2010, 17h23
  2. Mettre en place des droits sur une vue différents de ceux de la table-source ?
    Par Antoun dans le forum Administration et Installation
    Réponses: 14
    Dernier message: 15/02/2010, 14h13
  3. mettre en place un timeout sur une instruction
    Par grinder59 dans le forum C#
    Réponses: 10
    Dernier message: 04/02/2009, 10h24
  4. Mettre en place une bordure sur le hover d'un lien
    Par lesenbei dans le forum Mise en page CSS
    Réponses: 4
    Dernier message: 27/06/2007, 09h39
  5. Réponses: 18
    Dernier message: 06/02/2007, 12h26

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