2012-01-03 36 views
9

Giả sử ổ cắm TCP trên máy chủ lưu trữ cục bộ Linux đang ở trạng thái kết nối với máy chủ từ xa. Máy chủ lưu trữ cục bộ đang sử dụng epoll_wait để được thông báo về các sự kiện trên socket với máy chủ từ xa.Sao chép và tắt máy 1 chiều từ xa

Nếu máy chủ từ xa đã gọi:

shutdown(s,SHUT_WR); 

trên ổ cắm kết nối của nó để chỉ nó được thực hiện truyền, những gì sự kiện (s) sẽ epoll_wait lợi nhuận trên các máy chủ địa phương cho socket của nó?

Tôi giả sử EPOLLIN sẽ luôn được trả lại và cuộc gọi recv tiếp theo sẽ trả về 0 để cho biết phía từ xa đã kết thúc truyền.

Điều gì về EPOLLHUP hoặc EPOLLRDHUP? (Và sự khác nhau giữa hai sự kiện này) là gì?

Hoặc thậm chí EPOLLERR?

Nếu máy chủ từ xa gọi "đóng" thay vì "tắt", bạn có trả lời cho bất kỳ thay đổi nào ở trên không?

Trả lời

18

Tôi tự trả lời sau khi thực hiện việc nâng hạng nặng để tìm câu trả lời.

Ổ cắm nghe cho sự kiện epoll thường sẽ nhận được một sự kiện EPOLLRDHUP (ngoài EPOLLIN) sự kiện cờ khi đồng nghiệp từ xa gọi đóng hoặc tắt máy (SHUT_WR). Điều này không có nghĩa là ổ cắm đã chết. Các cuộc gọi tiếp theo để recv() sẽ trả về bất kỳ dữ liệu chưa đọc nào trên socket và cuối cùng "0" sẽ được trả về để chỉ EOF. Nó thậm chí có thể gửi dữ liệu trở lại nếu peer từ xa chỉ làm một nửa gần của ổ cắm của nó.

Một ngoại lệ đáng chú ý là nếu đồng đẳng từ xa đang sử dụng tùy chọn SO_LINGER được bật trên ổ cắm của nó với giá trị nán lại là "0". Kết quả của việc đóng một socket như vậy có thể dẫn đến một TCP RST được gửi thay vì một FIN. Từ những gì tôi đã đọc, một sự kiện thiết lập lại kết nối sẽ tạo ra một EPOLLHUP hoặc EPOLLERR. (Tôi không có thời gian để xác nhận, nhưng nó có ý nghĩa).

Có một số tài liệu để đề xuất có các triển khai Linux cũ hơn không hỗ trợ EPOLLRDHUP, do đó EPOLLHUP được tạo ra thay thế.

Và đối với những gì nó có giá trị, trong trường hợp cụ thể của tôi, tôi thấy rằng nó không phải là quá thú vị để có mã rằng trường hợp đặc biệt EPOLLHUP hoặc EPOLLRDHUP sự kiện. Thay vào đó, chỉ cần xử lý các sự kiện này giống như EPOLLIN/EPOLLOUT và gọi recv() (hoặc gửi() khi thích hợp). Nhưng hãy chú ý đến các mã trả lại được trả về từ recv() và gửi().

+1

Tôi có thêm câu hỏi về hành vi ở đây, vì vậy tôi đã đi sâu vào các tương tác này: https://medium.com/where-the-flamingcow-roams/down-the-epoll-rabbit-hole-5c0447cb6329 – flamingcow

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