Làm thế nào để phía máy chủ `TIME_WAIT` thực sự hoạt động?


11

Tôi biết có khá nhiều câu hỏi SE về vấn đề này và tôi tin rằng tôi đã đọc nhiều câu hỏi như vậy trước khi đến thời điểm này.

Theo "phía máy chủ TIME_WAIT", ý tôi là trạng thái của cặp ổ cắm phía máy chủ đã đóng () được khởi tạo ở phía máy chủ.

Tôi thường thấy những tuyên bố này nghe có vẻ mâu thuẫn với tôi:

  1. Phía máy chủ TIME_WAITlà vô hại
  2. Bạn nên thiết kế các ứng dụng mạng của mình để có các máy khách khởi tạo close (), do đó, ứng dụng khách phải chịu TIME_WAIT

Lý do tôi thấy mâu thuẫn này là vì TIME_WAITtrên máy khách có thể là một vấn đề - máy khách có thể chạy hết các cổng có sẵn, vì vậy, về bản chất, chúng tôi khuyên bạn nên chuyển gánh nặng TIME_WAITsang phía máy khách, nơi có thể gặp sự cố, từ phía máy chủ không phải là vấn đề.

Phía khách hàng TIME_WAITtất nhiên chỉ là một vấn đề đối với số lượng hạn chế các trường hợp sử dụng. Hầu hết các giải pháp máy chủ-máy khách sẽ liên quan đến một máy chủ và nhiều máy khách, khách hàng thường không xử lý được khối lượng kết nối đủ lớn để nó trở thành một vấn đề và ngay cả khi chúng xảy ra, vẫn có một số khuyến nghị để "hoàn toàn" ( trái ngược SO_LINGERvới thời gian chờ 0 hoặc can thiệp với tcp_tw sysctls) chiến đấu phía khách hàng TIME_WAITbằng cách tránh tạo quá nhiều kết nối quá nhanh. Nhưng điều đó không phải lúc nào cũng khả thi, ví dụ như đối với lớp ứng dụng như:

  • hệ thống giám sát
  • máy phát điện tải
  • proxy

Mặt khác, tôi thậm chí không hiểu phía máy chủ TIME_WAIThữu ích như thế nào . Lý do TIME_WAITthậm chí còn có, là bởi vì nó ngăn chặn việc bơm TCPcác mảnh cũ vào dòng mà họ không còn thuộc về. Đối với phía khách hàng TIME_WAIT, việc này được thực hiện bằng cách đơn giản là không thể tạo kết nối với cùng ip:portcác cặp mà kết nối cũ này có thể có (các cặp đã sử dụng bị khóa bởi TIME_WAIT). Nhưng đối với phía máy chủ, điều này không thể được ngăn chặn vì địa chỉ cục bộ sẽ có cổng chấp nhận và luôn luôn giống nhau và máy chủ không thể (AFAIK, tôi chỉ có bằng chứng thực nghiệm) từ chối kết nối đơn giản vì một đồng đẳng đến sẽ tạo ra cặp địa chỉ giống nhau đã tồn tại trong bảng ổ cắm.

Tôi đã viết một chương trình cho thấy TIME-WAIT phía máy chủ bị bỏ qua. Hơn nữa, vì thử nghiệm đã được thực hiện vào ngày 127.0.0.1, hạt nhân phải có một bit đặc biệt thậm chí cho nó biết đó là phía máy chủ hay phía máy khách (vì nếu không thì bộ dữ liệu sẽ giống nhau).

Nguồn: http://pastebin.com/5PWjkjEf , đã thử nghiệm trên Fedora 22, cấu hình mạng mặc định.

$ gcc -o rtest rtest.c -lpthread
$ ./rtest 44400 s # will do server-side close
Will initiate server close
... iterates ~20 times successfully
^C
$ ss -a|grep 44400
tcp    TIME-WAIT  0      0            127.0.0.1:44400         127.0.0.1:44401   
$ ./rtest 44500 c # will do client-side close
Will initiate client close
... runs once and then
connecting...
connect: Cannot assign requested address

Vì vậy, đối với phía máy chủ TIME_WAIT, các kết nối trên cùng một cặp cổng chính xác có thể được thiết lập lại ngay lập tức và thành công và đối với phía máy khách TIME-WAIT, ở lần lặp thứ hai connect()đã thất bại một cách chính đáng

Tóm lại, câu hỏi có hai phần:

  • Có phải phía máy chủ TIME_WAITthực sự không làm gì cả, và chỉ còn lại như vậy bởi vì RFCyêu cầu nó phải làm?
  • Là lý do đề xuất cho khách hàng để bắt đầu close () vì máy chủ TIME_WAITlà vô dụng?

Bạn sẽ không chạy ra khỏi cổng trừ khi bạn chỉ có 1 khách hàng. Bạn có 65535 cổng cho mỗi kết hợp IP máy khách / máy chủ. Kết nối từ 1.2.3.4:1111 khác với 4.3.2.1:1111. Nó chỉ mất vài byte bộ nhớ cho mỗi kết nối TIME_WAIT.
Marki555

Câu trả lời:


1

Trong thuật ngữ TCP phía máy chủ ở đây có nghĩa là máy chủ có ổ cắm ở trạng thái LISTEN.

RFC1122 cho phép ổ cắm ở trạng thái TIME-WAIT chấp nhận kết nối mới với một số điều kiện

        When a connection is closed actively, it MUST linger in
        TIME-WAIT state for a time 2xMSL (Maximum Segment Lifetime).
        However, it MAY accept a new SYN from the remote TCP to
        reopen the connection directly from TIME-WAIT state, if it:

Để biết chi tiết chính xác về các điều kiện, vui lòng xem RFC1122 . Tôi mong muốn cũng phải có một MỞ thụ động phù hợp trên ổ cắm (ổ cắm ở trạng thái LISTEN).

MỞ hoạt động (cuộc gọi kết nối phía máy khách) không có ngoại lệ như vậy và phải báo lỗi khi ổ cắm ở TIME-WAIT, theo RFC793 .

Tôi đoán về đề xuất trên máy khách (theo thuật ngữ TCP, máy chủ thực hiện OPEN tức là kết nối) được khởi tạo gần giống như của bạn, trong trường hợp phổ biến, nó sẽ phát tán các ổ cắm TIME-WAIT trên nhiều máy chủ hơn, nơi có nhiều tài nguyên cho các ổ cắm. Trong trường hợp phổ biến, khách hàng không gửi SYN sẽ sử dụng lại ổ cắm TIME-WAIT trên máy chủ. Tôi đồng ý rằng để áp dụng khuyến nghị như vậy vẫn phụ thuộc vào trường hợp sử dụng.


0

Đây có lẽ là ví dụ rõ ràng nhất về những gì TIME-WAIT thực sự làm và quan trọng hơn là tại sao nó quan trọng. Nó cũng giải thích lý do tại sao nên tránh một số mẹo 'chuyên gia' trên các máy Linux để 'giảm' TIME-WAIT '.


Vẫn không giải thích điều gì xảy ra khi kết nối máy khách-> máy chủ được bắt đầu và một máy chủ có cặp đó bị khóa trong TIME_WAIT
Pawel Veselov

Vui lòng xem stackoverflow.com/questions/1490196/ Mạnh - Câu trả lời có những gì bạn đang tìm kiếm.
Khushil

0

Một phiên tcp được xác định bởi tupple (sourceIP, sourcePort, DestIP, DestPort). Do đó TIME_WAIT không hoạt động trên mọi kết nối tcp.

Về phía đóng cửa, trong một số trường hợp, đóng từ phía máy khách có thể giảm ổ cắm TIME_WAIT trên máy chủ, do đó giảm một chút bộ nhớ. Trong trường hợp khi không gian ổ cắm có thể cạn kiệt (do cạn kiệt cổng phù du) (ví dụ: máy khách tham lam có nhiều kết nối đến cùng một máy chủ), vấn đề này cần được giải quyết ở bất kỳ phía nào.


Vui lòng giải thích; Khi bạn hỏi liệu TW phía máy chủ có làm gì không, bạn tự hỏi liệu kết nối tương tự có thể được sử dụng lại trong khoảng thời gian TW không. Câu trả lời là không bởi vì kết nối, như được xác định bởi tupple, chiếm một vị trí trong bảng tcp của máy chủ. Nếu khách hàng cố gắng mở cùng một kết nối sớm, nó sẽ nhận được RST, từ chối hiệu quả kết nối tcp. Nhân tiện, bài viết từ Khushil rất mô tả.
basos

Tôi rất xin lỗi, câu trả lời của bạn thực sự trả lời câu hỏi, tôi đã đọc sai và rút lại nhận xét của mình. Tuy nhiên, điều này cũng có vẻ không chính xác, vì tôi có mã dường như chứng minh rằng không có sự bảo vệ nào từ phía máy chủ TIME_WAIT(tôi đã cập nhật câu hỏi với thông tin đó). Tài liệu tham khảo của @ Khushil không bao gồm các TIME_WAITtrường hợp phía máy chủ đủ chi tiết.
Pawel Veselov

-2

Bạn không bao giờ có thể chắc chắn với một giao thức không đáng tin cậy, rằng bạn đã nhận được tin nhắn cuối cùng từ thiết bị ngang hàng của mình, do đó, thật nguy hiểm khi cho rằng đồng nghiệp của bạn đã cúp điện thoại khá đột ngột. Một nhược điểm lớn của giao thức TCP là chỉ có thể mở đồng thời 65000 cổng. Nhưng cách để khắc phục điều này sẽ là chuyển đến một trang trại máy chủ, có quy mô tốt hơn với tải, hơn là tái chế số cổng một cách nhanh chóng. Ở đầu máy khách, rất có thể bạn sẽ hết cổng nếu đó là máy trạm cơ bản.


Tôi rất xin lỗi, nhưng điều này không trả lời câu hỏi của tôi.
Pawel Veselov
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.