W jaki sposób serwer dowiaduje się, do którego portu klienta wysyłać?


26

Jak rozumiem, dzieje się tak, gdy klient wysyła żądanie połączenia:

  1. Serwer będzie powiązany z określonym numerem portu. Numer portu jest zawsze powiązany z procesem nasłuchiwania. Ponieważ tylko serwer nasłuchuje połączeń przychodzących, nie musimy wiązać się po stronie klienta
  2. Serwer będzie nasłuchiwał na tym numerze portu.
  3. Klient wyśle connect()zapytanie.
  4. Serwer zaakceptuje żądanie za pomocą accept(). Gdy tylko serwer zaakceptuje żądanie klienta, jądro przydziela losowy numer portu dla serwera w celu dalszego, send()a receive()ponieważ ten sam numer portu na serwerze nie może być używany do wysyłania i nasłuchiwania, a poprzedni port jest nadal nasłuchuje nowych połączeń

Biorąc to wszystko pod uwagę, w jaki sposób serwer dowiaduje się, na którym porcie odbiera klient? Wiem, że klient wyśle ​​segmenty TCP z portem źródłowym i docelowym, więc serwer użyje portu źródłowego tego segmentu jako portu docelowego, ale jaką funkcję wywołuje serwer, aby dowiedzieć się o tym porcie? Czy to accept()jest


Odpowiedzi:


33

Jest to część nagłówka TCP (lub UDP itp.) W pakiecie. Tak więc serwer dowiaduje się, ponieważ mówi to klient. Jest to podobne do sposobu, w jaki wyszukuje adres IP klienta (który jest częścią nagłówka IP).

Np. Każdy pakiet TCP zawiera nagłówek IP (przynajmniej ze źródłowym adresem IP, docelowym adresem IP i protokołem [TCP]). Następnie jest nagłówek TCP (z portem źródłowym i docelowym oraz więcej).

Kiedy jądro odbiera pakiet SYN (początek połączenia TCP) ze zdalnym adresem IP 10.11.12.13 (w nagłówku IP) i zdalnym portem 12345 (w nagłówku TCP), wówczas zna zdalny adres IP i port . Odsyła SYN | ACK. Jeśli otrzyma potwierdzenie ACK, listenpołączenie zwraca nowe gniazdo skonfigurowane dla tego połączenia.

Gniazdo TCP jest jednoznacznie identyfikowane przez cztery wartości (zdalny adres IP, lokalny adres IP, zdalny port, lokalny port). Możesz mieć wiele połączeń / gniazd, o ile przynajmniej jedno z nich się różni.

Zazwyczaj port lokalny i lokalny adres IP będą takie same dla wszystkich połączeń z procesem serwera (np. Wszystkie połączenia z sshd będą na lokalnym IP: 22). Jeśli jedno zdalne urządzenie nawiąże wiele połączeń, każde użyje innego zdalnego portu. Więc wszystko oprócz zdalnego portu będzie takie samo, ale to dobrze - tylko jeden z czterech musi się różnić.

Możesz użyć np. Wirehsark, aby zobaczyć pakiet, który oznaczy dla ciebie wszystkie dane. Oto podświetlony port źródłowy (zauważ, że jest podświetlony w zdekodowanym pakiecie, a także zrzut heksowy u dołu):

Wireshark pokazuje pakiet TCP SYN


> Dziękuję za wyjaśnienie. Masz na myśli, że nowy deskryptor gniazda serwera (tj. Krotka) uzyskany po accept () będzie miał dane klienta portu i adresu klienta, a ten nowy serwer deskryptora gniazda wysyła i odbiera dane do i od klienta. Nowy deskryptor pliku gniazda będzie miał nowy numer portu serwera przypisany przez jądro, ip serwera, ip klienta i port klienta. Mam rację?
Subi Suresh

@SubiSuresh tak, krotka jest przechowywana w jądrze, powiązana z tym deskryptorem pliku.
derobert

> Dzięki derobert. Więc doszedłem do wniosku, że nowy deskryptor gniazda serwera będzie miał port klienta i adres klienta, który serwer uzyska z metody accept (). Rozumiem dobrze, prawda?
Subi Suresh

@SubiSuresh Tak, zgadza się. Z punktu widzenia aplikacji zwykle nie przejmujesz się (z wyjątkiem logowania). Jądro zapewnia, że ​​dane write(itp.) Trafią we właściwe miejsce.
derobert

> dziękuję za pomoc i myślę, że mam rację. ;-)
Subi Suresh

2

„Żądanie połączenia ( connect()zwykle wywołanie systemowe programu klienckiego ) powoduje trójdrożny uścisk dłoni . Pierwszy pakiet trójdrożnego uścisku dłoni (od klienta do serwera) ma ustawioną flagę SYN i zawiera numer portu TCP programu klienta jądro przypisuje do niego.

Możesz to zobaczyć w artykule na temat pakietów Nmap vs. Natural SYN . Dekodowanie pakietu SYN Nmap ma frazę „source.60058> dest.22”. „Prawidłowe dekodowanie pakietu SYN” zawiera zwrot „source.35970> dest.80”. Dwa pakiety SYN informują zdalne jądro, że pakiety pochodzą odpowiednio z portu TCP 60058 i portu 35970.


> Ale Bruce, co dzieje się w zapleczu, ale jak mój serwer faktycznie pobiera takie szczegóły, jak numer portu, ponieważ zwykle w programach serwera klienta, nigdy nie widziałem żadnej funkcji do pobierania portu klienta i adresu klienta
Subi Suresh

Wywołanie systemowe getpeername()powinno pozwolić ci to zrobić na dowolnym otwartym gnieździe. accept()Wywołanie systemowe że kod serwer ma użyć, aby uzyskać deskryptor gniazda do komunikowania się z powrotem do klienta ma parametr ( „sockaddr” W moich stronach man), który zawiera adres IP potencjalnego klienta i numer portu TCP.
Bruce Ediger,

> Nie przejmuj się, jeśli wykonam elloborate. Ze wszystkich danych wejściowych zrozumiałem, że accept () ma strukturę sockaddr_in wypełnioną szczegółami klienta, a nowy deskryptor gniazda serwera zwrócony po accept () automatycznie otrzyma port i adres klienta. Właśnie dlatego jesteśmy w stanie wysyłać za pomocą send (nowy deskryptor gniazda serwera). Mam nadzieję, że jestem do rzeczy? Chodzi o to, aby upewnić się, że to, co zrozumiałem, jest prawidłowe. Czy dobrze?
Subi Suresh

@SubiSuresh - Wierzę, że napisałeś prawdę.
Bruce Ediger,

1

Gniazdo TCP jest gniazdem zorientowanym strumieniowo. Dwa deskryptory gniazd (należące do Ciebie i Twojego partnera) są niezawodnie połączone. Więc nie musisz się martwić o port klienta - po prostu napisz swój deskryptor gniazda!

Ponadto, możesz się zalogować do getsockname (2), jeśli naprawdę chcesz to wiedzieć (może do logowania).


0

Połączenie jest zdefiniowane przez krotkę (źródłowy adres IP, port źródłowy, docelowy adres IP, port docelowy). Odpowiedzi są odwrotne.


@vondrand W tym momencie zrozumiałem. Ale z jakiej funkcji serwer dowiaduje się o numerze portu klienta? Bez znajomości numeru portu klienta, w jaki sposób zostanie wysłany. Czy więc serwer używa struktury w accept () do pobrania klienta Port ?
Subi Suresh
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.