socket.shutdown vs socket.c Đóng


122

Gần đây tôi đã thấy một chút mã trông như thế này (dĩ nhiên sock là một đối tượng socket):

sock.shutdown(socket.SHUT_RDWR)
sock.close()

Chính xác mục đích của việc gọi tắt máy trên ổ cắm và sau đó đóng lại là gì? Nếu nó tạo ra sự khác biệt, ổ cắm này đang được sử dụng cho IO không chặn.

Câu trả lời:


38

Đây là một lời giải thích :

Khi ổ cắm không còn cần thiết, chương trình gọi có thể loại bỏ ổ cắm bằng cách áp dụng chương trình con đóng cho bộ mô tả ổ cắm. Nếu một ổ cắm phân phối đáng tin cậy có dữ liệu liên quan đến nó khi đóng, hệ thống tiếp tục thử truyền dữ liệu. Tuy nhiên, nếu dữ liệu vẫn chưa được gửi, hệ thống sẽ loại bỏ dữ liệu. Nếu chương trình ứng dụng không sử dụng cho bất kỳ dữ liệu đang chờ xử lý nào, nó có thể sử dụng chương trình con tắt trên ổ cắm trước khi đóng nó.


241

Gọi closeshutdowncó hai hiệu ứng khác nhau trên ổ cắm bên dưới.

Điều đầu tiên cần chỉ ra là socket là một tài nguyên trong HĐH cơ bản và nhiều tiến trình có thể có một điều khiển cho cùng một socket bên dưới.

Khi bạn gọi closenó làm giảm số đếm của tay cầm và nếu số lượng tay cầm đạt đến 0 thì ổ cắm và kết nối liên quan sẽ thực hiện thủ tục đóng bình thường (gửi FIN / EOF đến ngang hàng một cách hiệu quả) và ổ cắm được giải phóng.

Điều cần chú ý ở đây là nếu số lượng tay cầm không đạt đến 0 vì một quá trình khác vẫn có một tay cầm cho ổ cắm thì kết nối không được đóng và ổ cắm không bị hủy.

Mặt khác, việc gọi shutdownđể đọc và viết sẽ đóng kết nối cơ bản và gửi FIN / EOF cho bạn bè bất kể có bao nhiêu tiến trình có xử lý đến ổ cắm. Tuy nhiên, nó không phân bổ ổ cắm và bạn vẫn cần gọi gần sau đó.


câu trả lời tuyệt vời, tôi không bao giờ bận tâm để tìm hiểu những gì shutdown()không :)
Matt Joiner

2
Có thể tắt máy () để đọc khiến nó gửi gói FIN không? tức là tắt máy (sock_fd, 1);
ernesto

Nó sẽ là thông minh để luôn luôn gọi .shutdown()và trên đường tiếp theo .close()? Hoặc nên có một sự chậm trễ ở giữa?
Luc

@Luc Hoàn toàn phụ thuộc vào những gì bạn đang làm.
Robert S. Barnes

2
@Luc Sau đó, chỉ cần đóng là tốt miễn là không có quá trình khác có xử lý với ổ cắm.
Robert S. Barnes

17

Giải thích về tắt máy và đóng cửa: Tắt máy duyên dáng (msdn)

Tắt máy (trong trường hợp của bạn) cho biết ở đầu kia của kết nối, không có ý định đọc thêm hoặc ghi vào ổ cắm. Sau đó đóng lại giải phóng bất kỳ bộ nhớ liên quan đến ổ cắm.

Bỏ qua tắt máy có thể khiến ổ cắm nán lại trong ngăn xếp HĐH cho đến khi kết nối được đóng một cách duyên dáng.

IMO tên 'tắt máy' và 'đóng' là sai lệch, 'đóng' và 'phá hủy' sẽ nhấn mạnh sự khác biệt của chúng.


Nó không chỉ ra cho đầu kia rằng không có ý định đọc thêm. Tắt máy để đọc không gửi bất cứ điều gì cho các đồng nghiệp.
Hầu tước Lorne

7

nó được đề cập ngay trong phần Lập trình ổ cắm HOWTO ( py2 / py3 )

Ngắt kết nối

Nói đúng ra, bạn nên sử dụng shutdownmột ổ cắm trước bạn close. Đây shutdownlà một lời khuyên cho các ổ cắm ở đầu kia. Tùy thuộc vào đối số mà bạn vượt qua, điều đó có thể có nghĩa là tôi sẽ không gửi nữa, nhưng tôi vẫn sẽ nghe nghe , hoặc tôi không nghe, câu đố hay! Mùi. Tuy nhiên, hầu hết các thư viện ổ cắm đã quá quen thuộc với các lập trình viên bỏ qua việc sử dụng phần nghi thức này mà thông thường a closegiống như shutdown(); close(). Vì vậy, trong hầu hết các tình huống, không cần phải tắt máy rõ ràng.

...


Thông tin này không chính xác. Chỉ cần tắt ổ cắm để ghi nếu (1) bạn đã thực hiện quá trình và chắc chắn muốn gửi FIN ngay bây giờ hoặc (2) bạn đang tham gia vào giao thức đọc lẫn nhau để cả hai cùng đóng đồng thời. Nếu không thì close()đủ. Tài liệu Python nên được sửa.
Hầu tước Lorne

4

Không phải mã này ở trên sai sao?

Cuộc gọi đóng trực tiếp sau cuộc gọi tắt có thể làm cho kernel loại bỏ tất cả các bộ đệm đi.

Theo http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not- đáng tin cậy một người cần phải chờ giữa tắt máy và đóng cho đến khi đọc trả về 0.


Không chính xác. Nhân sẽ chỉ loại bỏ bộ đệm gửi đi nếu kết nối đã được đặt lại, điều này có thể xảy ra nếu ứng dụng cục bộ chưa đọc tất cả dữ liệu gửi đến đang chờ xử lý hoặc nếu ngang hàng đã bị lỗi với SO_Linger, điều mà họ không nên làm . Không cần thiết phải ngủ, thậm chí không cần phải tắt máy trước khi đóng cửa. Có rất nhiều thông tin sai lệch về vấn đề này.
Hầu tước Lorne


1

Tắt máy (1), buộc ổ cắm không gửi thêm dữ liệu

Điều này hữu ích trong

1- Xả đệm

2- Phát hiện lỗi lạ

3- Bảo vệ an toàn

Hãy để tôi giải thích thêm, khi bạn gửi dữ liệu từ A đến B, nó không được đảm bảo để gửi đến B, nó chỉ được đảm bảo được gửi đến bộ đệm A os, sau đó sẽ gửi nó đến bộ đệm B os

Vì vậy, bằng cách gọi tắt máy (1) trên A, bạn xóa bộ đệm của A và một lỗi được đưa ra nếu bộ đệm không trống, tức là: dữ liệu chưa được gửi đến ngang hàng

Tuy nhiên, điều này là không thể khắc phục được, vì vậy bạn có thể làm điều đó sau khi bạn đã gửi hoàn toàn tất cả dữ liệu của mình và bạn muốn chắc chắn rằng nó ít nhất ở bộ đệm ngang hàng


Tắt máy không ép buộc. Tình hình đệm không thay đổi. Và nếu bộ đệm không trống, không có lỗi nào được đưa ra. FIN chỉ đơn thuần là được xử lý đằng sau dữ liệu đang chờ xử lý. Trả lời là hoàn toàn không chính xác.
Hầu tước Lorne
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.