Câu trả lời:
Q: Có bao nhiêu quá trình có thể lắng nghe trên một cổng cụ thể?
A: nhiều như bạn có thể sinh sản.
Tuy nhiên, đối với SOCK_STREAM
ổ cắm ít nhất và trừ khi bạn sử dụng SO_REUSEPORT
tùy chọn (mới trong Linux 3.9), một quy trình không thể liên kết ổ cắm với điểm cuối cục bộ (địa chỉ + cổng cho TCP, tên tệp cho Unix ...) nếu có một ổ cắm khác bị ràng buộc cái đó (hoặc một cái nghe trên cổng đó với địa chỉ ký tự đại diện).
Vì vậy, trừ khi bạn sử dụng SO_REUSEPORT, cách duy nhất để có các quy trình khác nhau lắng nghe trên cùng một cổng là có các mô tả tệp tương ứng của chúng trỏ đến cùng một mô tả tệp mở (vào cùng một ổ cắm).
Điều đó xảy ra tự động khi bạn fork()
một quá trình. Nếu fd 3 trỏ đến ổ cắm TCP đang nghe trên địa chỉ ký tự đại diện và cổng 12345, cả hai quá trình sau ngã ba sẽ lắng nghe trên cổng đó trên fd đó ( zsh
cú pháp bên dưới):
$ zmodload zsh/net/tcp
$ ztcp -ld 3 12345
$ sleep 10 &
$ lsof -ni tcp:12345
COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
zsh 26277 stephane 3u IPv4 506354 0t0 TCP *:12345 (LISTEN)
sleep 26988 stephane 3u IPv4 506354 0t0 TCP *:12345 (LISTEN)
Đối với các quy trình không liên quan, cách duy nhất (mà tôi biết) cho một quy trình để có quyền truy cập vào ổ cắm nghe đó là sử dụng SCM_RIGHT
cơ chế để truyền fds (thực sự giống như mô tả tệp mở ) giữa các quy trình sử dụng ổ cắm miền unix.
Bạn sẽ nhận thấy rằng một đối số listen()
là tồn đọng .
Ngay khi có một ổ cắm lắng nghe điểm cuối đã cho, kernel sẽ bắt đầu chấp nhận các kết nối đến điểm cuối đó ( backlog là một gợi ý cho kernel về số lượng nó có thể chấp nhận mà accept
ứng dụng không thể chỉnh sửa được ).
Sau đó, quá trình đầu tiên thực hiện accept()
trên bất kỳ fds nào trỏ đến ổ cắm nghe (hoặc bất kỳ ổ cắm nghe nào SO_REUSEPORT
) sẽ nhận được kết nối đến. accept()
tạo một ổ cắm mới và trả về một fd mới cho điều đó socket
. Đổi lại, fd đó có thể được nhân đôi (một fd mới trỏ đến cùng một ổ cắm) và các tiến trình con sẽ kế thừa ổ cắm được kết nối đó giống như cách chúng nghe.
Câu trả lời này thảo luận về TCP trên IPv4.
Chỉ có một quá trình có thể lắng nghe các kết nối mới. Bạn sẽ gặp lỗi "địa chỉ đã sử dụng" nếu có nhiều hơn một quy trình cố gắng yêu cầu cùng một cổng.
Điều này hoàn toàn khác với số lượng quy trình đang tích cực sử dụng cổng đó.
Có một cái nhìn vào đầu ra sau đây:
remote local state
*:* - 4.3.2.1:5000 LISTENING
1.2.3.4:12345 - 4.3.2.1:5000 CONNECTED
4.5.6.7:83247 - 4.3.2.1:5000 CONNECTED
Những gì cần phải là duy nhất, là 4-tuple (remote-ip, remote-port, local-ip, local-port)
. Vì (remote-ip, remote-port)
ở trạng thái LISTENING là một *:*
, chỉ có một quá trình có thể lắng nghe.
Ứng dụng nghe sẽ bắt đầu một luồng / tác vụ / tiến trình mới trên mỗi kết nối đến.
*
) và nhớ rằng IPv4 và IPv6 là các ngăn xếp riêng biệt.