2010-07-28 8 views
31

Tôi biết vấn đề này nên được khắc phục với System.setProperty ("http.keepAlive", "false"); trước openConnection, nhưng điều đó không hiệu quả với tôi. Trước tiên hãy thử trên mã này hoạt động, thứ hai không thành công. Ngay cả khi tôi thử yêu cầu này sau ít hơn 5 giây, nó cũng hoạt động. Nếu tôi chờ đợi nhiều hơn thế, nó thất bại một lần nữaHttpUrlConnection.openConnection thất bại lần thứ hai

Đây là mã của tôi:

System.setProperty("http.keepAlive", "false"); 
    HttpURLConnection conn = (HttpURLConnection) mURL.openConnection(); 
    conn.setUseCaches(false); 
    conn.setRequestProperty("Connection","Keep-Alive"); 
    conn.setRequestProperty("User-Agent", useragent); 
    conn.setConnectTimeout (30000) ; 
    conn.setDoOutput(true); 
     conn.setDoInput(true); 

    consumer.sign(conn); 
    InputSource is = new InputSource(conn.getInputStream()); 

tôi nhận được ngoại lệ trên dòng cuối cùng:

java.io.IOException: Write error: I/O error during system call, Broken pipe 
W/System.err(2164): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.nativewrite(Native Method) 
W/System.err(2164): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.access$600(OpenSSLSocketImpl.java:55) 
W/System.err(2164): at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl$SSLOutputStream.write(OpenSSLSocketImpl.java:583) 
W/System.err(2164): at java.io.OutputStream.write(OutputStream.java:82) 
W/System.err(2164): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.sendRequest(HttpURLConnectionImpl.java:1332) 
W/System.err(2164): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequestInternal(HttpURLConnectionImpl.java:1656) 
W/System.err(2164): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.doRequest(HttpURLConnectionImpl.java:1649) 
W/System.err(2164): at org.apache.harmony.luni.internal.net.www.protocol.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:1153) 
W/System.err(2164): at org.apache.harmony.luni.internal.net.www.protocol.https.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:253) 

Liệu ai đó có một ý tưởng về những gì sai ở đây ? Cảm ơn!

Trả lời

3

Tôi đã giải quyết được sự cố. Ở đây tôi để lại cho bạn mã, trong trường hợp nó có thể hữu ích cho một ai đó. Về cơ bản tôi thấy một xu hướng trên Google để sử dụng HttpClient/HttpGet thay vì HttpUrlConnection. Vì vậy, tôi cố gắng với những lớp học, và mọi thứ làm việc:

final HttpClient client = new DefaultHttpClient(); 
final HttpGet conn = new HttpGet(mURL.toString()); 

OAuthConsumer consumer = mOAuthManager.getPostConsumer(); 
consumer.sign(conn); 
HttpResponse response = client.execute(conn); 
InputSource is = new InputSource(response.getEntity().getContent()); 
+10

google bây giờ đề xuất sử dụng HttpUrlConnection (bắt đầu từ Gingerbread) vì một vài lỗi đó đã được sửa: http: // android-developers.blogspot.com/2011/09/androids-http-clients.html –

+8

Tại sao giải pháp này giải quyết được sự cố? –

+0

Sớm hay muộn, đặc biệt là với Android M đang phát triển, HttpClient đang trở nên không được chấp nhận hiệu quả. URLConnection được đề xuất cho các ứng dụng có thời lượng sử dụng dài. – Josh

0

Tôi tin rằng sự cố của bạn nằm trong thứ tự mã của bạn. Kiểm tra các phương thức đó trong URLConnection JavaDocs - setRequestProperty không nên được gọi sau khi kết nối được thực hiện trên mUrl.openConnection(). Nó có thể được làm việc lần đầu tiên bởi vì kết nối được thực hiện, sau đó bạn đang thay đổi cài đặt mà không ảnh hưởng đến bất cứ điều gì cho đến khi thời gian tiếp theo bạn cố gắng để thực hiện một kết nối. Hãy thử sử dụng hàm tạo HttpURLConnection để bạn có thể gọi connect() sau khi bạn đã thiết lập các thuộc tính.

+1

Cảm ơn câu trả lời của bạn, nhưng tôi e rằng điều đó sẽ không hiệu quả. Đây là những gì tài liệu API nói: Một URLConnection chỉ có thể được thiết lập sau khi instantiation nhưng trước khi kết nối với tài nguyên từ xa. Trong trường hợp của tôi, kết nối thực tế xảy ra trong: conn.getInputStream() và sau khi thiết lập tiêu đề – ggomeze

28

Kết nối hồ bơi được sử dụng bởi HttpURLConnection khi nó được giữ kết nối còn sống được chia như vậy mà nó cố gắng sử dụng các kết nối đã bị đóng cửa bởi máy chủ. Theo mặc định, Android đặt KeepAlive trên tất cả các kết nối.

System.setProperty("http.keepAlive", "false"); là giải pháp khắc phục sự cố KeepAlive cho tất cả các kết nối để bạn tránh lỗi trong nhóm kết nối.

conn.setRequestProperty("Connection","Keep-Alive"); bật KeepAlive cho kết nối cụ thể này, về cơ bản đảo ngược những gì System.setProperty("http.keepAlive", "false"); thực hiện.

Ngoài ra tôi luôn gọi một cách rõ ràng connect() vì nó giúp bạn biết rõ nơi bạn đang kết thúc thiết lập kết nối của mình. Tôi không chắc chắn nếu gọi phương pháp này là tùy chọn hay không.

System.setProperty("http.keepAlive", "false"); 
HttpURLConnection conn = (HttpURLConnection) mURL.openConnection(); 
conn.setUseCaches(false); 
conn.setRequestProperty("User-Agent", useragent); 
conn.setConnectTimeout(30000); 
conn.setDoOutput(true); 
conn.setDoInput(true); 
consumer.sign(conn); 

conn.connect(); 

InputSource is = new InputSource(conn.getInputStream()); 
+0

Cảm ơn @fonetik vì câu trả lời và giải thích !! Tôi không thể kiểm tra nó ngay bây giờ khi tôi chuyển đến HttpClient, nhưng tôi chắc chắn điều này có thể giúp người khác. Cảm ơn một lần nữa! – ggomeze

+0

@ user464773 'System.setProperty (" http.keepAlive "," false ");' vô hiệu hóa _Keep Alive_ trên tất cả các kết nối của ứng dụng. Đây là những gì chúng tôi muốn vì _Keep Alive_ sẽ luôn gây ra lỗi. Sử dụng 'conn.setRequestProperty (" connection "," close ");' chỉ vô hiệu hóa _Keep Alive_ cho 'conn', để cánh cửa mở cho một lỗi khi chúng ta quên thêm nó vào bất kỳ kết nối nào. Tôi không biết liệu lỗi đó có được trả lại cho Harmony hay không nhưng nhóm Android đã biết về nó: http://code.google.com/p/android/issues/detail?id=7786 – barrycburton

+0

Cảm ơn, Đó chỉ là những gì tôi đang tìm kiếm – TacoEater

23

Bạn không cần các System.setProperty("http.keepAlive", "false");

Tất cả bạn cần là conn.setRequestProperty("connection", "close");

này sửa chữa vấn đề này nhưng có hiệu quả tiêu diệt giữ alives và do đó có khả năng làm cho nhiều kết nối chậm hơn (đó là một sự xấu hổ). Tôi đã xem xét thông qua trình theo dõi lỗi hài hòa nhưng không thể tìm thấy bất cứ thứ gì.

@fonetik, bạn có biết điều này đã được nâng lên với sự hài hòa không? Tôi có nghĩa là không phải là nó giúp nhiều vì một lỗi khác liên quan đến luni http vẫn chưa được chỉ định sau hơn một tháng.

+0

conn.setRequestProperty ("kết nối", "đóng"); đã làm cho tôi. Đơn giản và hiệu quả. Tôi đang làm việc với URLconnection cho Android L và M. – Josh

1

Lỗi này đã được sửa trong phiên bản Android2.3, như chúng ta biết System.setProperty("http.keepAlive", "false"); không phải là giải pháp tốt, bởi vì trên thiết bị di động, tạo mỗi kết nối là mỗi lần có chi phí cao.

0

Khi tôi đang cố gắng để mở kết nối https nó đang làm việc tốt nhưng lần thứ hai nó không thành công vì tôi đã thiết lập giá trị thuộc tính hệ thống thay vì kết nối HttpsURLConnection. Tôi đã có số java.io.IOException: Lỗi ghi: Sự cố I/O khi mở kết nối https lần thứ hai. Tôi đã sử dụng mã sau trong đơn đăng ký của tôi.

System.setProperty("http.proxyHost", proxy); 
System.setProperty("http.proxyPort", port); 

Nhưng khi tôi thay đổi như cũ bên dưới nó hoạt động tốt.

javax.net.ssl.HttpsURLConnection ucon = (javax.net.ssl.HttpsURLConnection) urlWPF.openConnection(proxyserver); 

ucon.setRequestProperty("http.proxyHost", proxy); 
ucon.setRequestProperty("http.proxyPort", port); 

Nếu bạn đặt thuộc tính hệ thống, nó sẽ áp dụng cho toàn bộ ứng dụng. Nếu bạn muốn đặt lại như cũ, bạn có thể làm theo hai cách. Một là bạn phải làm mới máy chủ và thứ hai là bạn phải thay đổi các HttpsURLConnection.setRequestProperty được đề cập ở trên, nơi cần thiết.