2012-01-15 49 views
23

Bạn có thể an toàn/an toàn để close() ổ cắm trực tiếp sau send() cuối cùng không?close() cắm trực tiếp sau khi gửi(): không an toàn?

Tôi biết rằng TCP có nhiệm vụ cố gắng phân phối tất cả dữ liệu còn lại trong bộ đệm gửi ngay cả sau khi đóng socket, nhưng tôi có thể thực sự dựa vào đó không?

Tôi đảm bảo rằng không có dữ liệu còn lại trong bộ đệm nhận để không có RST nào được gửi sau khi đóng.


Trong trường hợp của tôi, lệnh đóng thực sự là mã cuối cùng trước khi gọi exit().

Ngăn xếp TCP thực sự tiếp tục thử và truyền dữ liệu ngay cả sau khi quá trình gửi nó đã chấm dứt? Đó có phải là đáng tin cậy như chờ đợi một thời gian chờ tùy ý trước khi gọi close() bằng cách đặt SO_LINGER?

Tức là, làm cùng thời gian chờ TCP áp dụng hoặc chúng ngắn hơn? Với bộ đệm gửi lớn và kết nối chậm, thời gian thực sự chuyển tất cả dữ liệu đệm có thể đáng kể.


Tôi không quan tâm đến việc được thông báo về byte cuối cùng đã gửi; Tôi chỉ muốn họ cuối cùng đến được máy chủ từ xa một cách đáng tin cậy nhất có thể.

Xác nhận lớp ứng dụng không phải là một tùy chọn (giao thức là HTTP và tôi đang viết một máy chủ nhỏ).

+0

Nó phụ thuộc vào việc thực hiện, nhưng nói chung, có, 'close()' sẽ xóa bất kỳ dữ liệu nào còn lại trong bộ đệm trước khi nó thực sự rơi xuống ổ cắm. Mileage có thể thay đổi nếu bạn chấm dứt toàn bộ quá trình ngoài việc gọi 'close()'. – aroth

+2

@aroth Mileage sẽ * không * thay đổi nếu bạn thoát khỏi quá trình. Không có sự khác biệt giữa hai trường hợp. Nếu bạn muốn duy trì điều ngược lại, vui lòng cung cấp một tài liệu tham khảo có thẩm quyền. – EJP

+0

@EJP - Tham chiếu có thẩm quyền về những gì * có thể xảy ra trong các chương trình tùy ý? Tôi không nghĩ một thứ như vậy tồn tại. Nhưng nó đủ đơn giản để đưa ra một ví dụ hợp lý. Giả sử bạn có một chương trình ủy nhiệm tất cả các hoạt động mạng cho một luồng riêng biệt, giống như hầu hết các chương trình nên. Có thể cho chủ đề chính để chấm dứt quá trình (duyên dáng hoặc cách khác) trong khi chủ đề nền đang gọi 'close()'. Cuộc gọi có thành công trong trường hợp đó không? Tôi nghi ngờ điều đó. Cấp, những gì bạn nói nên giữ đúng cho bất kỳ chương trình đơn luồng. Nhưng không phải tất cả các chương trình đều đơn luồng. – aroth

Trả lời

20

Tôi đã đọc rất nhiều ultimate SO_LINGER page. Tôi khuyên bạn nên đọc nó. Nó thảo luận về các trường hợp cạnh của việc truyền dữ liệu lớn liên quan đến các socket TCP.

tôi không phải là chuyên gia trong việc SO_LINGER, nhưng trên mã máy chủ của tôi (vẫn còn trong phát triển tích cực) Tôi thực hiện như sau:

  1. Sau byte cuối cùng được gửi qua send(), tôi gọi là " shutdown (sock, SHUT_WR) "để kích hoạt FIN được gửi đi.

  2. Sau đó đợi cuộc gọi recv() tiếp theo trên socket đó để trả về 0 (hoặc recv trả về -1 và errno là bất kỳ điều gì khác mà EAGAIN/EWOULDBLOCK).

  3. Sau đó, máy chủ thực hiện lệnh đóng() trên ổ cắm.

Giả định là khách hàng sẽ đóng socket của mình trước sau khi nhận được tất cả byte của phản hồi.

Nhưng tôi có thời gian chờ được thực thi giữa lần gửi cuối cùng() và khi recv() biểu thị EOF. Nếu khách hàng không bao giờ đóng kết thúc của mình của kết nối, máy chủ sẽ từ bỏ chờ đợi và đóng kết nối anyway. Tôi đang ở 45-90 giây cho thời gian chờ này.

Tất cả các ổ cắm của tôi đều không bị chặn và tôi sử dụng thăm dò/epoll để được thông báo về các sự kiện kết nối dưới dạng gợi ý để xem đã đến lúc thử gọi lại recv() hay gửi().

+2

Điều đó có vẻ giống như một giải pháp rất tốt miễn là khách hàng đóng socket trước. Tuy nhiên, anh ta có thể không viết được nửa kết nối của mình ngay lập tức sau khi gửi yêu cầu không? Thông số HTTP không nói bất cứ điều gì về vấn đề đóng một nửa; Bạn có nghĩ rằng hành vi đó xảy ra trong các máy khách HTTP không? – lxgr

+0

No. Tôi đã thực hiện một số thuật toán wireshark quảng cáo đặc biệt để xác thực. Tôi khuyến khích bạn làm điều tương tự. Từ thử nghiệm sniffing gói của tôi - đôi khi máy chủ gửi FIN của nó sau khi phản ứng và khách hàng gửi FIN sau khi nhận được phản hồi. Tuy nhiên, hầu hết các máy khách http chỉ định tùy chọn "keep-alive" với máy chủ, vì vậy, các máy khách không khởi động được. Nói cách khác, tôi nghĩ rằng rất an toàn để giả định rằng khách hàng sẽ không đóng một nửa. – selbie

+0

Ngoài ra, khách hàng có thể chú ý đến tiêu đề Content-Length. Nó có thể là chính đáng rằng máy chủ không cần phải đóng hoặc tắt máy sau khi gửi tất cả các byte của mình, bởi vì khách hàng biết có bao nhiêu byte để mong đợi trong HTTP resposne. (Và máy chủ chắc chắn sẽ không đóng nếu nó hỗ trợ kết nối giữ-sống và nếu khách hàng yêu cầu nó). Nhưng trong các yêu cầu đơn giản hơn mà không cần giữ lại, máy chủ sẽ gửi một FIN sau khi phản hồi của anh ta đã được gửi đi. – selbie

Các vấn đề liên quan