2011-08-23 33 views
9

Tôi đang thực hiện một số thử nghiệm cố gắng cách ly một số hành vi kỳ lạ trong các thư viện (.NET). Khi tôi sử dụng Winsock API thông qua C++ và chỉ đơn giản gọi, closesocket(), tôi thấy bên cửa sổ gửi gói FIN/ACK và phía xa gửi lại một gói ACK. Đây là những gì tôi sẽ gọi là một duyên dáng gần gũi. Tuy nhiên, khi lập trình trong C# tôi không nhìn thấy những gì tôi sẽ gọi là một gần duyên dáng.Làm thế nào để ngăn chặn các thư viện .NET gửi gói RST đến gần

Trong C#, tôi mở ổ cắm và sau đó, khi đóng nó, tôi thấy các cửa sổ gửi gói FIN Chỉ khi lần đầu tiên gọi Socket.Shutdown(). Tuy nhiên, bất kể, khi tôi gọi Socket.Close() trong C#, một gói tin RST được gửi đi và kết nối được giảm xuống. Điều này làm tôi bối rối vì, từ những gì tôi đã đọc trên mạng, quá trình đóng TCP phải là FIN/ACK -> ACK (từ cả hai phía thực sự nhưng hiện tại, tôi chỉ quan tâm đến mặt "của tôi"); tức là không nên có một gói RST trong hỗn hợp. Từ những gì tôi đã đọc, rõ ràng, một gói RST chỉ được gửi khi người nhận không chắc chắn về trạng thái kết nối và muốn ra ngoài.

Tại sao gói RST này được gửi khi bị tắt theo kế hoạch trong .NET và hoàn toàn không bị ngừng hoạt động theo kế hoạch từ API winsock? Có cách nào để ngăn chặn việc truyền tải một gói RST trong một shutdown duyên dáng từ .NET?

Trong trường hợp nó quan trọng, trong cả hai đường dẫn mã, tôi đang đọc tất cả dữ liệu có sẵn trên socket trước khi gọi phương thức close() tương ứng.

Trả lời

0

Gần đây, bạn đã gặp phải sự cố tương tự khi ứng dụng đang nói POP3 với Exchange Server. Khi chương trình .NET kết thúc, nó đóng cửa không đúng lúc, và Exchange xử lý cuộc hội thoại POP3 là "hủy bỏ" và cuộn nó trở lại.

Lý do là tôi nghĩ TCP RST là thông báo "một chiều" - bạn không phải chờ trả lời. Vì vậy, đó là những gì NET gửi (. Hoặc có lẽ bất kỳ chương trình sau khi nó chấm dứt) Một giải pháp khả thi là để chờ đợi một chút sau khi đóng các ổ cắm và trước khi bỏ chương trình:

Thread.Sleep(5000); 

này làm việc cho vấn đề POP3 tôi đã đề cập trước đó ; thời gian chờ làm cho kết nối tắt một cách duyên dáng và Exchange không còn hủy bỏ phiên.

+1

Điều đó thật thú vị. Tôi sẽ phải xem điều gì xảy ra khi tôi thực hiện một giấc ngủ. Tôi tự hỏi những gì khác sẽ hiển thị bởi vì tôi không nghĩ rằng điều này là khả thi (nếu nó hoạt động) cho bối cảnh đầy đủ trong đó điều này đang xảy ra. Tôi đã thực hiện các chương trình bộ xương để cô lập hành vi. Cảm ơn dù sao mặc dù bởi vì tôi đã không nghĩ đến việc sử dụng một cuộc gọi giấc ngủ ở đây. –

3

Đọc NET doc của Socket.Close, đây là những gì tôi thấy:

Đối với các giao thức hướng kết nối, nó được khuyến khích mà bạn gọi Shutdown trước khi gọi phương thức Close. Điều này đảm bảo rằng tất cả các dữ liệu được gửi và nhận trên ổ cắm được kết nối trước khi nó được đóng lại. Nếu , bạn cần gọi Close mà không gọi tắt là Shutdown, bạn có thể đảm bảo dữ liệu được xếp hàng chờ truyền đi sẽ được gửi bằng cách đặt tùy chọn DontLinger Socket thành false và chỉ định khoảng thời gian khác. Đóng sau đó sẽ chặn cho đến khi dữ liệu này được gửi hoặc cho đến khi hết hạn được chỉ định hết hạn. Nếu bạn đặt DontLinger thành false và chỉ định khoảng thời gian chờ bằng không, Đóng phát hành kết nối và sẽ tự động loại bỏ dữ liệu đã gửi đi.

thực sự có ý nghĩa. Nếu vẫn còn dữ liệu trong bộ đệm (hệ điều hành một) và bạn ngắt kết nối hoặc hủy bỏ quá trình kết nối sẽ được đặt lại (thông tin chi tiết hơn trong thông số TCP).

Đến thời điểm RST được gửi, hãy kiểm tra TCP Guide.

Đoán của tôi là vẫn còn một số dữ liệu không được đặt hoặc chuyển tiếp hoặc trong bộ đệm gửi đi/phát sinh kích hoạt RST.

1

Mã sau có thể ngăn chặn gói RST. Đó là vì chờ 60 giây sau khi gửi gói FIN.

socket.Close(60); 

Mô tả phương pháp đóng là here.

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