2012-06-29 62 views
2

我升級現有的應用程序,並在新的版本我需要OS 5 - 的原因之一是,我想用的ConnectionFactory用於通過HTTP/HTTPS與我們的服務器進行通信,而無需添加所有使用BES,BIS,Direct TCP,Wifi等的URL參數。黑莓連接工廠超時

ConnectionFactory現在配置爲選擇通過首選類型連接到我們的服務的最佳方式。

我的連接代碼如下所示:

ConnectionFactory connectionFactory = new ConnectionFactory(); 
BisBOptions bisOptions = new BisBOptions(BIS_SECRET); 
connectionFactory.setTransportTypeOptions(TransportInfo.TRANSPORT_BIS_B, bisOptions); 
connectionFactory.setConnectionMode(ConnectionFactory.ACCESS_READ_WRITE); 
connectionFactory.setEndToEndDesired(true); 
connectionFactory.setPreferredTransportTypes(new int[] { TransportInfo.TRANSPORT_BIS_B, TransportInfo.TRANSPORT_MDS, 
TransportInfo.TRANSPORT_TCP_WIFI, TransportInfo.TRANSPORT_TCP_CELLULAR }); 
ConnectionDescriptor connectionDescriptor = connectionFactory.getConnection("https://myserver.com/serviceurl"); 
try { 
    HttpConnection con = (HttpConnection) connectionDescriptor.getConnection(); 
    byte[] bytes = parameter.toString().getBytes(UTF_8); 
    con.setRequestProperty(CONTENT_LENGTH, String.valueOf(bytes.length)); 
    os = con.openOutputStream(); 
    os.write(bytes); 
    os.flush(); 
    int responseCode = con.getResponseCode(); 
    if (responseCode == 401) { 
    throw new InvalidCredentialsException("Invalid credentials"); 
    } else if (responseCode != 200 && responseCode != 500) { 
    EventLogger.logEvent(RTSID, ("Response code " + responseCode + " " + con 
      .getResponseMessage()).getBytes(), EventLogger.ERROR); 
    EventLogger.logEvent(RTSID, bytes, EventLogger.ERROR); 
    throw new IOException("Invalid request"); 
    } 
    is = con.openInputStream(); 
    if (is != null) { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    int c = 0; 
    try { 
     c = is.read(); 
    } catch (Exception ex) { 
     c = -1; 
    } 
    while (c >= 0) { 
     baos.write(c); 
     try { 
     c = is.read(); 
     } catch (Exception ex) { 
     c = -1; 
     } 
    } 
    String response = new String(baos.toByteArray(), UTF_8); 
    try { 
     JSONObject jsonObject; 
     if (response.startsWith("[")) { 
     jsonObject = new JSONObject(); 
     jsonObject.put(ARRAY, new JSONArray(response)); 
     } else { 
     jsonObject = new JSONObject(response); 
     } 
     if (responseCode == 500) { 
     throw new Exception(jsonObject.getString("message")); 
     } 
     return jsonObject; 
    } catch (JSONException e) { 
     EventLogger.logEvent(RTSID, ("Exception occured: " + e.toString()).getBytes(), 
     EventLogger.ERROR); 
    } 
    } 
} finally { 
    if (is != null) { 
    try { 
     is.close(); 
    } catch (Exception e) { 
    } 
    } 
    if (os != null) { 
    try { 
     os.close(); 
    } catch (Exception e) { 
    } 
    } 
    if (con != null) { 
    try { 
     con.close(); 
    } catch (Exception e) { 
    } 
    } 
} 

我的問題是,這個工程沒有很好,當我手動添加連接參數到我的網址。我看到服務器日誌中的錯誤看起來像客戶端在某種超時後關閉連接。

下面是一些日誌的例子:

93.186.30.120 - - [28/Jun/2012:15:50:08 +0200] "POST /service/methodX HTTP/1.1" 400 145 "-" "myapp VendorID/301" 10012567 
93.186.22.118 - - [28/Jun/2012:16:30:56 +0200] "POST /service/methodY HTTP/1.1" 400 145 "-" "myapp VendorID/137" 10012435 
74.82.68.35 - - [28/Jun/2012:16:53:23 +0200] "POST /service/methodZ HTTP/1.1" 400 145 "-" "myapp BlackBerry9650/6.0.0.524 VendorID/105" 10012644 

的IP不會忽略來自RIM網絡 - 所以這些是連接從正在添加BIS

這些連接了狀態代碼400(無效請求)來自服務器

行末的大數字(例如10012644)顯示時間請求被以微秒在服務器上處理:10012644 =約10秒

不要的RIM服務器添加的10秒連接超時?這似乎相當短!

問題難以重現 - 有沒有人經歷過類似的事情?

+0

超時時間爲2分鐘。單獨使用HttpConnection。順便說一句,你可能會想通過調用'ConnectionFactory.setConnectionTimeout'來覆蓋它。而關於400,你是否忘記了請求中的任何內容? (比如,像SoapAction這樣的HTTP標頭)。你有https的證書嗎? –

回答

1

我找到了原因。問題是造成Apache模塊mod_reqtimeout的默認配置:

<IfModule reqtimeout_module> 

# mod_reqtimeout limits the time waiting on the client to prevent an 
# attacker from causing a denial of service by opening many connections 
# but not sending requests. This file tries to give a sensible default 
# configuration, but it may be necessary to tune the timeout values to 
# the actual situation. Note that it is also possible to configure 
# mod_reqtimeout per virtual host. 


# Wait max 20 seconds for the first byte of the request line+headers 
# From then, require a minimum data rate of 500 bytes/s, but don't 
# wait longer than 40 seconds in total. 
# Note: Lower timeouts may make sense on non-ssl virtual hosts but can 
# cause problem with ssl enabled virtual hosts: This timeout includes 
# the time a browser may need to fetch the CRL for the certificate. If 
# the CRL server is not reachable, it may take more than 10 seconds 
# until the browser gives up. 
RequestReadTimeout header=20-40,minrate=500 

# Wait max 10 seconds for the first byte of the request body (if any) 
# From then, require a minimum data rate of 500 bytes/s 
RequestReadTimeout body=10,minrate=500 

</IfModule> 

我猜是因爲通過RIM的BIS基礎設施發送請求的身體需要較長時間的黑莓客戶WER更難打。

將該值設置爲100秒,並監視客戶端是否仍然受到影響。