Tôi đang sử dụng DefaultHttpClient
với số ThreadSafeClientConnManager
trên Android (2.3.x) để gửi các yêu cầu HTTP đến máy chủ REST của tôi (trình kết nối được nhúng).Tại sao DefaultHttpClient gửi dữ liệu qua ổ cắm nửa đóng?
Sau ~ 200 giây không hoạt động, máy chủ sẽ đóng kết nối TCP bằng [FIN]. Ứng dụng khách Android phản hồi với [ACK]. Điều này nên và không để lại socket trong trạng thái nửa đóng (máy chủ vẫn đang nghe, nhưng không thể gửi dữ liệu). Tôi mong rằng khi khách hàng cố gắng sử dụng lại kết nối đó (thông qua HttpClient.execute
), DefaultHttpClient
sẽ phát hiện trạng thái nửa đóng, đóng socket ở phía máy khách (do đó gửi [FIN/ACK] để hoàn thành đóng) và mở một kết nối mới cho yêu cầu. Nhưng, có chà.
Thay vào đó, nó sẽ gửi yêu cầu HTTP mới qua ổ cắm nửa đóng. Chỉ sau khi gửi là trạng thái nửa đóng được phát hiện và socket đóng trên phía máy khách (với [FIN] được gửi đến máy chủ). Tất nhiên, máy chủ không thể đáp ứng yêu cầu (nó đã gửi [FIN]), vì vậy máy khách cho rằng yêu cầu thất bại và tự động thử lại thông qua một socket/kết nối mới.
Kết quả cuối cùng là máy chủ sẽ xem và xử lý hai bản sao của yêu cầu.
Bất kỳ ý tưởng nào về cách sửa lỗi này? (Máy chủ của tôi thực hiện điều chính xác với bản sao thứ hai, nhưng tôi thấy khó chịu rằng tải trọng được truyền hai lần.)
Không nên mặc địnhHttpClient phát hiện rằng socket đã được đóng khi lần đầu tiên cố gắng viết gói HTTP mới, đóng ổ cắm đó ngay lập tức và bắt đầu một ổ cắm mới? Tôi đang bối rối như thế nào một yêu cầu HTTP mới được gửi vào một phút ổ cắm sau khi máy chủ gửi một [FIN].
'AndroidHttpClient' không hành vi tương tự chính xác (ví dụ: một' DefaultHttpClient' với một 'ThreadSafeClientConnManager' để đảm bảo an toàn thread) ... có lẽ bạn có thể thử sử dụng đó? Tôi không biết nhiều về các chi tiết về cách kết nối ổ cắm hoạt động, nhưng chỉ là một gợi ý ... –