Zarówno wywołania systemowe, jak connect()
i bind()
wywołania systemowe „kojarzą” deskryptor pliku gniazda z adresem (zwykle jest to kombinacja ip / port). Ich prototypy to: -
int connect(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
i
int bind(int sockfd, const struct sockaddr *addr,
socklen_t addrlen);
Jaka jest dokładna różnica między 2 połączeniami? Kiedy stosować connect()
i kiedy bind()
?
W szczególności w niektórych przykładowych kodach klienta serwera stwierdzono, że klient używa, connect()
a serwer używa bind()
wywołania. Rozum nie był dla mnie do końca jasny.
c
sockets
network-programming
Siddhartha Ghosh
źródło
źródło
Odpowiedzi:
Aby lepiej zrozumieć, dowiedzmy się, gdzie dokładnie pojawia się łączenie i łączenie,
Oprócz rozmieszczenia dwóch połączeń, jak wyjaśnił Sourav,
bind () kojarzy gniazdo z jego adresem lokalnym [dlatego wiąże się po stronie serwera, aby klienci mogli używać tego adresu do łączenia się z serwerem.] connect () służy do łączenia się ze zdalnym adresem [serwera], dlatego jest po stronie klienta , connect [czytaj jako: połącz z serwerem] jest używane.
Nie możemy ich używać zamiennie (nawet jeśli mamy klienta / serwer na tej samej maszynie) ze względu na określone role i odpowiednią implementację.
Będę dalej zalecał skorelowanie tych połączeń uzgadniania TCP / IP.
Więc kto wyśle tutaj SYN, będzie to connect (). Podczas gdy bind () służy do definiowania punktu końcowego komunikacji.
Mam nadzieję że to pomoże!!
źródło
Jedna linia:
bind()
na własny adres,connect()
na zdalny adres.Cytując ze strony podręcznika man
bind()
iz tego samego dla
connect()
W celu wyjaśnienia,
bind()
kojarzy gniazdo z jego adresem lokalnym [dlatego po stronie serwerabind
s, aby klienci mogli używać tego adresu do łączenia się z serwerem].connect()
służy do łączenia się ze zdalnym adresem [serwera], dlatego jest po stronie klienta, używane jest połączenie [czytaj jako: połącz z serwerem].źródło
interchangeable
local
-> sam proces,remote
-> inny proces.bind mówi działającemu procesowi, aby zajął port. tj. powinien połączyć się z portem 80 i nasłuchiwać przychodzących żądań. z bind, twój proces staje się serwerem. kiedy używasz connect, mówisz swojemu procesowi, aby połączył się z portem, który jest JUŻ używany. Twój proces staje się klientem. różnica jest ważna: bind chce portu, który nie jest używany (aby mógł go przejąć i stać się serwerem), a connect chce portu, który jest już używany (aby mógł się z nim połączyć i rozmawiać z serwerem)
źródło
Z Wikipedii http://en.wikipedia.org/wiki/Berkeley_sockets#bind.28.29
połączyć():
Wywołanie systemowe connect () łączy gniazdo, zidentyfikowane przez jego deskryptor pliku, ze zdalnym hostem określonym przez adres tego hosta na liście argumentów.
Niektóre typy gniazd są bezpołączeniowe, najczęściej są to gniazda protokołu datagramów użytkownika. Dla tych gniazd connect nabiera specjalnego znaczenia: domyślny cel wysyłania i odbierania danych zostaje ustawiony na podany adres, co pozwala na użycie funkcji takich jak send () i recv () na gniazdach bezpołączeniowych.
connect () zwraca liczbę całkowitą reprezentującą kod błędu: 0 oznacza sukces, a -1 oznacza błąd.
wiązać():
bind () przypisuje gniazdo do adresu. Kiedy gniazdo jest tworzone za pomocą funkcji socket (), otrzymuje tylko rodzinę protokołów, ale nie otrzymuje adresu. To powiązanie z adresem musi zostać wykonane za pomocą wywołania systemowego bind (), zanim gniazdo będzie mogło zaakceptować połączenia z innymi hostami. bind () przyjmuje trzy argumenty:
sockfd, deskryptor reprezentujący gniazdo do wykonania wiązania. my_addr, wskaźnik do struktury sockaddr reprezentującej adres do powiązania. addrlen, pole socklen_t określające rozmiar struktury sockaddr. Bind () zwraca 0 w przypadku sukcesu i -1, jeśli wystąpi błąd.
Przykłady: 1.) Korzystanie z Connect
2.) Przykład wiązania:
Mam nadzieję, że to wyjaśnia różnicę
Należy pamiętać, że deklarowany typ gniazda będzie zależał od tego, czego potrzebujesz, jest to niezwykle ważne
źródło
Myślę, że pomogłoby ci to w zrozumieniu, gdybyś myślał o
connect()
ilisten()
jako o odpowiednikach, a nie oconnect()
ibind()
. Powodem tego jest to, że możesz wywołać lub pominąćbind()
wcześniej, chociaż rzadko jest to dobry pomysł, aby wywołać to wcześniejconnect()
lub nie dzwonić wcześniejlisten()
.Jeśli pomaga myśleć kategoriami serwerów i klientów, to jest
listen()
to znak rozpoznawczy tego pierwszego iconnect()
drugiego.bind()
można znaleźć - lub nie znaleźć - na obu.Jeśli założymy, że nasz serwer i klient znajdują się na różnych komputerach, łatwiej będzie zrozumieć różne funkcje.
bind()
działa lokalnie, co oznacza, że wiąże koniec połączenia na maszynie, na której jest wywoływany, z żądanym adresem i przypisuje żądany port do użytkownika. Robi to niezależnie od tego, czy ta maszyna będzie klientem, czy serwerem.connect()
inicjuje połączenie z serwerem, co oznacza, że łączy się z żądanym adresem i portem na serwerze od klienta. Ten serwer prawie na pewno zadzwoniłbind()
wcześniejlisten()
, abyś mógł wiedzieć, na którym adresie i porcie się z nim połączyć za pomocąconnect()
.Jeśli nie zadzwonisz
bind()
, port i adres zostaną niejawnie przypisane i powiązane na komputerze lokalnym podczas wywoływaniaconnect()
(klienta) lublisten()
(serwera). Jest to jednak efekt uboczny obu, a nie ich cel. Tak wyznaczony port jest efemeryczny.Ważną kwestią jest tutaj to, że klient nie musi być związany, ponieważ klienci łączą się z serwerami, więc serwer będzie znał adres i port klienta, nawet jeśli używasz portu efemerycznego, zamiast wiązania się z czymś konkretnym. Z drugiej strony, chociaż serwer mógłby dzwonić
listen()
bez wywoływaniabind()
, w tym scenariuszu musiałby znaleźć przypisany mu port efemeryczny i przekazać go każdemu klientowi, z którym chce się połączyć.Zakładam, jak wspomniałeś,
connect()
że interesuje Cię TCP, ale przenosi się to również na UDP, gdzie nie wywołaniebind()
przed pierwszymsendto()
(UDP jest bez połączenia) powoduje również niejawne przypisanie i powiązanie portu i adresu. Jedną z funkcji, której nie można wywołać bez powiązania, jest tarecvfrom()
, która zwróci błąd, ponieważ bez przypisanego portu i związanego adresu nie ma z czego odbierać (lub za dużo, w zależności od tego, jak interpretujesz brak wiązania).źródło
Za długo; Don't Read: Różnica polega na tym, czy ustawiany jest adres źródłowy (lokalny) czy docelowy / port. Krótko mówiąc,
bind()
ustaw źródło iconnect()
ustaw miejsce docelowe. Niezależnie od protokołu TCP lub UDP.bind()
bind()
ustaw lokalny (źródłowy) adres gniazda. To jest adres, pod którym odbierane są pakiety. Pakiety wysyłane przez gniazdo zawierają ten adres jako adres źródłowy, więc drugi host będzie wiedział, gdzie odesłać swoje pakiety.Jeśli odbiór nie jest potrzebny, adres źródłowy gniazda jest bezużyteczny. Protokoły takie jak TCP wymagają włączonego odbierania w celu prawidłowego wysyłania, ponieważ host docelowy odsyła potwierdzenie, gdy przybył jeden lub więcej pakietów (tj. Potwierdzenie).
connect()
connect()
uruchamia kod TCP, aby spróbować nawiązać połączenie z drugą stroną.connect()
ustawia tylko domyślny adres, na który są wysyłane pakiety, jeśli nie określono żadnego adresu. Kiedyconnect()
nie jest używanysendto()
lubsendmsg()
musi być używany, zawierający adres docelowy.Kiedy
connect()
wywoływana jest funkcja wysyłania lub, a żaden adres nie jest powiązany, Linux automatycznie wiąże gniazdo z losowym portem. Aby uzyskać szczegółowe informacje techniczne,inet_autobind()
zapoznaj się z kodem źródłowym jądra Linux.Dodatkowe uwagi
listen()
to tylko TCP.struct sockaddr_in
) składa się z adresu IP (patrz nagłówek IP ) oraz portu TCP lub UDP (patrz nagłówek TCP i UDP ).źródło