2012-11-16 14 views
8

私は定期的にポーリングを行い、特定の応答に基づいてメッセージを送信するサーバー用のJavaクライアントを設定します。クラスに使用した戦略は次のとおりです。Apache HttpClientサーバー戦略への複数のポーリング接続

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(); 
     } 
    } 
} 

私は約3秒でポーリングを行うスレッドを開始します。ポーリング結果に基づいてメインスレッドからメッセージを送信できます。コードは機能しますが、次の2つの例外を与え続けますが、その間に作業を続けます。

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. 

私はただ例外をミュートすることができますが、何が起こっているのか知りたいと思います。私はGoogle経由で解決策を見つけることができませんでした。私はコンテンツを消費しようとしましたが、sendメソッドで新しいHttpPostオブジェクトを作成しました。そのようなものですが、これまで何も助けてくれませんでした。

このような状況に適した戦略は何ですか?現時点ではHttpPostオブジェクトにkeep-aliveヘッダーを設定しています。それ以外には、私は何もしていないと思う。私はこれが全体的な戦略と関係していると思います。私はすべての接続のために新しいオブジェクトを作りたいとは思っていませんが、どのレベルの再利用が推奨されるかもわかりません。助けてくれてありがとう。ああ..これはHttpClientです。4.2.2

答えて

1

@ Saadさんの回答は非常に役に立ちましたが、多くの同時リクエストでテスト用URLを読み込もうとすると遅延が発生しました。

問題を解決したバージョンが更新されました。

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

これらのメソッドは同期されておらず、別のスレッドから呼び出しています。 poll()操作が進行中にコードがsend()を呼び出そうとする可能性はありますか?私は同じオブジェクトを使用して同時に2つの要求をしようとすると、HttpClientがそれを好まないと思います。

(これが問題である場合は、些細な修正プログラムは、あなたがそれらを呼び出すスレッドをブロックする気にしないと仮定すると、両方の方法にsynchronizedキーワードを追加することです。)

0

これはやり過ぎかもしれないが、あなたはhttp接続ハンドリング専用のスレッドを持つことを検討するかもしれません。このスレッドは、ポーリングするか、送信する信号が来るまでスリープ状態になります。この利点は、1つの接続だけが使用されることです。

1

私は以下のコードを使用して終了しました。それはうまくいかない理由があります。

DefaultHttpClient client = new DefaultHttpClient(); 
ClientConnectionManager mgr = client.getConnectionManager(); 
HttpParams params = client.getParams(); 
client = new DefaultHttpClient(new ThreadSafeClientConnManager(params, mgr.getSchemeRegistry()), params); 
関連する問題