2012-11-16 4 views
8

Ich richte einen Java-Client für einen Server ein, den ich regelmäßig abrufe und Meldungen basierend auf einer bestimmten Antwort sende. Die Strategie, die ich für die Klasse verwendet habe, lautet wie folgt:Apache HttpClient Mehrere Polling-Verbindungen zur Server-Strategie

public class PollingClient { 
    private HttpClient client = getHttpClient(); // I get a DefaultHttpClient this way so it's easier to add connection manager and strategy etc to the client later 
    private HttpPost httpPost = getHttpPost(); // same idea, I set headers there 

    public String poll() { 
     List<NameValuePair> formparams = new ArrayList<NameValuePair>(); 
     formparams.add(new BasicNameValuePair("id", someId)); 

     String responseString = null; 

     try { 
      UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, "UTF-8");   
      httppost.setURI(polluri)); 
      httppost.setEntity(formEntity); 
      HttpResponse response = httpclient.execute(httppost); 
      HttpEntity entity = response.getEntity(); 


      if (entity != null) { 
       responseString = EntityUtils.toString(entity); 
      } 

      EntityUtils.consume(entity); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 

    public void send(String msg) { 
     List<NameValuePair> formparams = new ArrayList<NameValuePair>(); 
     formparams.add(new BasicNameValuePair("msg", msg)); 
     formparams.add(new BasicNameValuePair("id", someId)); 

     String responseString = null; 

     try { 
      UrlEncodedFormEntity formEntity = new UrlEncodedFormEntity(formparams, "UTF-8"); 

      httppost.setURI(new URI(URL + "send")); 
      httppost.setEntity(formEntity); 

      HttpResponse response = httpclient.execute(httppost); 
      HttpEntity entity = response.getEntity(); 


      if (entity != null) { 
       responseString = EntityUtils.toString(entity); 
      } 

      EntityUtils.consume(entity); 

     } catch (Exception e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Ich starte einen Thread, der die Abfrage nach etwa 3 Sekunden abarbeitet. Ich kann die Nachrichten vom Hauptthread basierend auf den Umfrageergebnissen senden. Der Code funktioniert, gibt mir aber weiterhin die folgenden zwei Ausnahmen, arbeitet aber dazwischen weiter.

java.lang.IllegalStateException: Invalid use of BasicClientConnManager: connection still allocated. 
Make sure to release the connection before allocating another one. 

org.apache.http.NoHttpResponseException: The target server failed to respond. 

Ich könnte nur die Ausnahmen stummschalten, aber ich möchte wissen, was vor sich geht. Ich konnte keine Lösungen über Google finden. Ich habe versucht, Inhalt zu konsumieren, ein neues HttpPost-Objekt in der Sendemethode zu machen, so etwas, aber nichts hat bisher geholfen.

Was ist eine gute Strategie für eine Situation wie diese. Ich setze derzeit den keep-alive Header im HttpPost Objekt, falls das wichtig ist. Ansonsten glaube ich nicht, dass ich irgendetwas mache. Ich denke, das hat mit der Strategie insgesamt zu tun. Ich möchte nicht für jede Verbindung ein neues Objekt erstellen, aber ich weiß auch nicht, welche Stufe der Wiederverwendung empfohlen wird. Danke für jede Hilfe. Oh .. und das ist HttpClient 4.2.2

Antwort

1

@ Saads Antwort war sehr hilfreich, aber ich habe Verzögerungen erlebt, wenn ich versuchte, einzelne URL mit vielen gleichzeitigen Anfragen zu laden.

Hier ist eine aktualisierte Version, die das Problem gelöst hat.

DefaultHttpClient client = new DefaultHttpClient(); 
    ClientConnectionManager mgr = client.getConnectionManager(); 
    HttpParams params = client.getParams(); 
    int maxConnections = 100; 
    params.setParameter(ConnManagerPNames.MAX_CONNECTIONS_PER_ROUTE, new ConnPerRouteBean(maxConnections)); 
    params.setIntParameter(ConnManagerPNames.MAX_TOTAL_CONNECTIONS, maxConnections); 
    ThreadSafeClientConnManager conman = new ThreadSafeClientConnManager(params, mgr.getSchemeRegistry()); 
    client = new DefaultHttpClient(conman, params); 
0

Diese Methoden sind nicht synchronisiert und Sie rufen von verschiedenen Threads. Ist es möglich, dass Ihr Code versucht, send() aufzurufen, während eine poll() -Operation läuft? Ich stelle mir vor, HttpClient wird es nicht mögen, wenn Sie versuchen, zwei Anfragen zur gleichen Zeit mit dem gleichen Objekt zu machen.

(Wenn dies das Problem ist, wäre eine triviale fix sein, um die synchronisierte Schlüsselwort für beide Methoden an, um die Fäden blockiert nicht davon aus, dass etwas dagegen, sie nennen.)

0

Diese Overkill sein könnte, aber Sie könnte in Erwägung ziehen, einen Thread für die HTTP-Verbindungsübergabe einzurichten. Dieser Thread würde den Schlaf so lange verbringen, bis er abstimmen oder ein Signal senden kann. Der Vorteil hierbei ist, dass nur eine Verbindung jemals benutzt wird.

1

Ich endete mit dem folgenden Code. Es funktioniert ... habe keine Ahnung warum.

Verwandte Themen