Không có câu trả lời nào hiện có cho mọi người biết cách thức shutdown
và close
hoạt động ở cấp độ giao thức TCP, vì vậy rất đáng để thêm điều này.
Kết nối TCP tiêu chuẩn bị chấm dứt bởi quyết toán 4 chiều:
- Khi người tham gia không còn dữ liệu để gửi, nó sẽ gửi gói FIN cho người khác
- Bên kia trả lại ACK cho FIN.
- Khi bên kia cũng kết thúc truyền dữ liệu, nó sẽ gửi một gói FIN khác
- Người tham gia ban đầu trả về một ACK và hoàn tất chuyển khoản.
Tuy nhiên, có một cách "xuất hiện" khác để đóng kết nối TCP:
- Một người tham gia gửi một gói RST và từ bỏ kết nối
- Phía bên kia nhận được một RST và sau đó cũng từ bỏ kết nối
Trong thử nghiệm của tôi với Wireshark, với các tùy chọn ổ cắm mặc định, shutdown
sẽ gửi một gói FIN đến đầu kia nhưng đó là tất cả những gì nó làm. Cho đến khi bên kia gửi cho bạn gói FIN, bạn vẫn có thể nhận dữ liệu. Khi điều này xảy ra, bạn Receive
sẽ nhận được kết quả kích thước 0. Vì vậy, nếu bạn là người đầu tiên tắt "gửi", bạn nên đóng ổ cắm sau khi nhận xong dữ liệu.
Mặt khác, nếu bạn gọi close
trong khi kết nối vẫn hoạt động (phía bên kia vẫn hoạt động và bạn cũng có thể có dữ liệu chưa được lưu trong bộ đệm hệ thống), một gói RST sẽ được gửi sang phía bên kia. Điều này là tốt cho các lỗi. Ví dụ: nếu bạn nghĩ rằng bên kia đã cung cấp dữ liệu sai hoặc họ từ chối cung cấp dữ liệu (tấn công DOS?), Bạn có thể đóng ổ cắm ngay lập tức.
Ý kiến của tôi về các quy tắc sẽ là:
- Cân nhắc
shutdown
trước close
khi có thể
- Nếu bạn đã nhận xong (nhận được dữ liệu kích thước 0) trước khi bạn quyết định tắt máy, hãy đóng kết nối sau khi gửi lần cuối (nếu có) kết thúc.
- Nếu bạn muốn đóng kết nối bình thường, hãy tắt kết nối (với SHUT_WR và nếu bạn không quan tâm đến việc nhận dữ liệu sau thời điểm này, với SHUT_RD), và đợi cho đến khi bạn nhận được dữ liệu kích thước 0, sau đó đóng ổ cắm.
- Trong mọi trường hợp, nếu có bất kỳ lỗi nào khác xảy ra (ví dụ như hết thời gian chờ), chỉ cần đóng ổ cắm.
Triển khai lý tưởng cho SHUT_RD và SHUT_WR
Những điều sau đây chưa được thử nghiệm, tin tưởng vào rủi ro của riêng bạn. Tuy nhiên, tôi tin rằng đây là một cách làm việc hợp lý và thiết thực.
Nếu ngăn xếp TCP chỉ nhận được tắt máy với SHUT_RD, nó sẽ đánh dấu kết nối này là không có thêm dữ liệu dự kiến. Bất kỳ read
yêu cầu đang chờ xử lý và tiếp theo (bất kể chủ đề nào họ tham gia) sau đó sẽ được trả về với kết quả không có kích thước. Tuy nhiên, kết nối vẫn hoạt động và có thể sử dụng - ví dụ: bạn vẫn có thể nhận dữ liệu OOB. Ngoài ra, HĐH sẽ bỏ bất kỳ dữ liệu nào nó nhận được cho kết nối này. Nhưng đó là tất cả, không có gói nào sẽ được gửi sang phía bên kia.
Nếu ngăn xếp TCP chỉ nhận được tắt máy chỉ với SHUT_WR, nó sẽ đánh dấu kết nối này vì không thể gửi thêm dữ liệu. Tất cả các yêu cầu ghi đang chờ xử lý sẽ kết thúc, nhưng các yêu cầu ghi tiếp theo sẽ không thành công. Hơn nữa, một gói FIN sẽ được gửi đến một phía khác để thông báo cho họ rằng chúng tôi không có nhiều dữ liệu để gửi.