Làm thế nào để máy chủ tìm ra cổng khách hàng để gửi đến?


26

Theo tôi hiểu, đây là những gì xảy ra khi khách hàng thực hiện yêu cầu kết nối:

  1. Máy chủ sẽ được liên kết với một số cổng cụ thể. Số cổng luôn bị ràng buộc với một quá trình nghe. Vì chỉ có máy chủ đang lắng nghe các kết nối đến, chúng tôi không cần phải ràng buộc về phía máy khách
  2. Máy chủ sẽ tiếp tục lắng nghe số cổng đó.
  3. Khách hàng sẽ gửi connect()yêu cầu.
  4. Máy chủ sẽ chấp nhận yêu cầu sử dụng accept(). Ngay khi máy chủ chấp nhận yêu cầu của máy khách, kernel sẽ cấp phát một số cổng ngẫu nhiên cho máy chủ send()receive()vì cùng một số cổng trên máy chủ không thể được sử dụng để gửi cũng như nghe, và cổng trước vẫn còn lắng nghe những kết nối mới

Với tất cả những điều đó, làm thế nào để máy chủ tìm ra cổng mà khách hàng đang nhận được? Tôi biết máy khách sẽ gửi các phân đoạn TCP với một cổng nguồn và cổng đích, vì vậy máy chủ sẽ sử dụng cổng nguồn của phân đoạn đó làm cổng đích của nó, nhưng máy chủ gọi chức năng nào để tìm hiểu về cổng đó? Là nóaccept() không


Câu trả lời:


33

Đó là một phần của tiêu đề TCP (hoặc UDP, v.v.), trong gói. Vì vậy, máy chủ tìm ra bởi vì khách hàng nói với nó. Điều này tương tự như cách nó tìm ra địa chỉ IP của máy khách (là một phần của tiêu đề IP).

Ví dụ: mọi gói TCP bao gồm một tiêu đề IP (với IP nguồn, IP đích và giao thức [TCP], ít nhất). Sau đó, có một tiêu đề TCP (với cổng nguồn và cổng đích, cộng với nhiều hơn nữa).

Khi hạt nhân nhận được gói SYN (bắt đầu kết nối TCP) với IP từ xa là 10.11.12.13 (trong tiêu đề IP) và cổng từ xa 12345 (trong tiêu đề TCP), thì nó sẽ biết IP và cổng từ xa . Nó sẽ gửi lại một SYN | ACK. Nếu nó nhận được ACK trở lại, listencuộc gọi sẽ trả về một ổ cắm mới, được thiết lập cho kết nối đó.

Một ổ cắm TCP được xác định duy nhất bởi bốn giá trị (IP từ xa, IP cục bộ, cổng từ xa, cổng cục bộ). Bạn có thể có nhiều kết nối / ổ cắm, miễn là ít nhất một trong số đó khác nhau.

Thông thường, cổng cục bộ và IP cục bộ sẽ giống nhau cho tất cả các kết nối đến quy trình máy chủ (ví dụ: tất cả các kết nối đến sshd sẽ nằm trên local-ip: 22). Nếu một máy từ xa tạo nhiều kết nối, mỗi máy sẽ sử dụng một cổng từ xa khác nhau. Vì vậy, tất cả mọi thứ trừ cổng từ xa sẽ giống nhau, nhưng đó chỉ là một trong bốn điều tốt.

Bạn có thể sử dụng, ví dụ, cordhsark để xem gói và nó sẽ gắn nhãn tất cả dữ liệu cho bạn. Đây là cổng nguồn được tô sáng (chú ý nó được tô sáng trong gói được giải mã, cũng như kết xuất hex ở phía dưới):

Wireshark hiển thị gói TCP SYN


> Cảm ơn bạn đã giải thích. Vì vậy, bạn muốn nói rằng bộ mô tả ổ cắm máy chủ mới (tức là tuple) có được sau khi chấp nhận () sẽ có cổng khách hàng và chi tiết địa chỉ máy khách và sử dụng máy chủ mô tả ổ cắm mới đó đang gửi và nhận dữ liệu tới và từ client.New mô tả tệp ổ cắm mới sẽ có số cổng máy chủ mới được gán bởi kernel, ip máy chủ, ip máy khách và cổng máy khách. Tôi có đúng không?
Subi Suresh

@SubiSuresh có, bộ dữ liệu được lưu trữ bên trong kernel, được liên kết với bộ mô tả tệp đó.
derobert

> Cảm ơn derobert. Vì vậy, tôi đang kết luận rằng bộ mô tả ổ cắm máy chủ mới sẽ có cổng máy khách và địa chỉ máy khách, mà máy chủ có được từ accept (). Sự hiểu biết của tôi là ổn phải không?
Subi Suresh

@SubiSuresh Vâng, điều đó đúng. Từ quan điểm ứng dụng, bạn thường không quan tâm (ngoại trừ việc đăng nhập). Nhân đảm bảo dữ liệu bạn write(v.v.) đi đúng nơi.
derobert

> cảm ơn sự giúp đỡ của bạn và tôi nghĩ rằng tôi đã nhận được điểm. ;-)
Subi Suresh

2

"Yêu cầu kết nối ( connect()thường gọi cuộc gọi hệ thống của chương trình khách ) gây ra bắt tay ba bước . Gói đầu tiên của bắt tay 3 chiều (từ máy khách đến máy chủ) có đặt cờ SYN và bao gồm số cổng TCP của chương trình máy khách kernel gán cho nó.

Bạn có thể thấy điều này trong một bài viết về các gói Nmap vs Natural SYN . Giải mã gói Nmap SYN có cụm từ "source.60058> Dest.22". Giải mã "gói tin hợp pháp" có cụm từ "source.35970> Dest.80" trong đó. Hai gói SYN cho hạt nhân từ xa biết rằng các gói từ cổng TCP 60058 và cổng 35970 tương ứng.


> Nhưng Bruce đang xảy ra ở phần cuối. Nhưng cách máy chủ của tôi thực sự tìm nạp các chi tiết như số cổng thông thường trong các chương trình máy chủ, tôi chưa bao giờ thấy bất kỳ chức năng nào để tìm nạp cổng máy khách và địa chỉ máy khách
Subi Suresh

Cuộc gọi hệ thống getpeername()sẽ cho phép bạn làm điều đó trên bất kỳ ổ cắm mở. Cuộc accept()gọi hệ thống mà mã máy chủ phải sử dụng để có được bộ mô tả tệp ổ cắm để liên lạc lại với máy khách có một tham số ("sockaddr" trong các trang man của tôi) có chứa địa chỉ IP của khách hàng tiềm năng và số cổng TCP.
Bruce Ediger

> Xin đừng bận tâm nếu tôi elloborate. Từ tất cả các đầu vào tôi đã hiểu rằng accept () có cấu trúc sockaddr_in chứa đầy các chi tiết máy khách và bộ mô tả ổ cắm máy chủ mới được trả về sau khi accept () sẽ tự động có cổng và địa chỉ của máy khách. Đó có phải là lý do tại sao chúng tôi có thể gửi bằng cách sử dụng send (bộ mô tả ổ cắm máy chủ mới). Tôi hy vọng, có đúng không? Điều này chỉ để đảm bảo rằng những gì tôi đã hiểu là đúng.
Subi Suresh

@SubiSuresh - Tôi tin rằng bạn đã viết sự thật.
Bruce Ediger

1

Ổ cắm TCP là một ổ cắm định hướng theo luồng. Hai mô tả ổ cắm (thuộc sở hữu của bạn và đồng nghiệp của bạn) được kết nối đáng tin cậy. Vì vậy, bạn không phải lo lắng về cổng của khách hàng - chỉ cần viết mô tả ổ cắm của bạn!

Ngoài ra, hãy thoải mái lấy tên (2) nếu bạn thực sự muốn biết điều đó (có thể đăng nhập).


0

Kết nối được xác định bởi một tuple (IP nguồn, cổng nguồn, IP đích, cổng đích). Câu trả lời đi ngược lại.


@vondrand Điểm đó tôi hiểu von. Nhưng máy chủ biết chức năng nào về số cổng khách? Từ đó biết số cổng khách sẽ gửi như thế nào. Máy chủ có sử dụng cấu trúc trong accept () để tìm nạp máy khách không Hải cảng ?
Subi Suresh
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.