socket connect() vs bind()

Lesezeit: 10 Minuten

Benutzeravatar von Siddhartha Ghosh
Siddhartha Ghosh

Beide connect() und bind() Systemaufrufe „assoziieren“ den Socket-Dateideskriptor mit einer Adresse (typischerweise eine IP/Port-Kombination). Ihre Prototypen sind wie:-

int connect(int sockfd, const struct sockaddr *addr,
               socklen_t addrlen);

und

int bind(int sockfd, const struct sockaddr *addr,
            socklen_t addrlen);

Was ist der genaue Unterschied zwischen 2 Anrufen? Wann sollte man verwenden connect() und wann bind()?

Insbesondere wurde in einigen Beispielserver-Clientcodes festgestellt, dass der Client verwendet connect() und Server verwendet die bind() Anruf. Grund war mir nicht ganz klar.

  • In einem Satz: Binden ist an die lokale Adresse, Verbinden ist an die entfernte Adresse.

    – SHR

    19. November 2014 um 11:53 Uhr

Benutzeravatar von Jain Rach
Jain Rach

Um das Verständnis zu verbessern, lassen Sie uns herausfinden, wo genau binden und verbinden ins Bild kommt,

YQ5ES

Zusätzlich zur Positionierung von zwei Anrufen, wie von Sourav klargestellt,

bind() verknüpft den Socket mit seiner lokalen Adresse [that’s why server side binds, so that clients can use that address to connect to server.]
connect() wird verwendet, um eine Verbindung zu einer Remote herzustellen [server] Adresse, deshalb Clientseite, verbinden [read as: connect to server] wird genutzt.

Wir können sie aufgrund spezifischer Rollen und entsprechender Implementierung nicht austauschbar verwenden (selbst wenn wir Client/Server auf demselben Computer haben).

Ich werde weiterhin empfehlen, diese Aufrufe mit dem TCP/IP-Handshake zu korrelieren.

Geben Sie hier die Bildbeschreibung ein

Also, wer hier SYN sendet, wird connect() sein. Während bind() zum Definieren des Kommunikationsendpunkts verwendet wird.

Hoffe das hilft!!

  • Dank bro. Mit der Grafik lässt sich alles schnell entziffern. Können Sie sagen, was hier der Unterschied ist, wenn wir udp verwenden?

    – apm

    23. Juli 2015 um 12:17 Uhr


  • accept()
    sollte bis zur Verbindung vom Client unter
    Block verschoben werden

    – tschodt

    30. September 2015 um 12:44 Uhr


  • Ich denke, alle Knoten in einem Netzwerk in einem P2P-Netzwerk sollten Bind verwenden, habe ich recht?

    – kapil

    23. Februar 2020 um 13:49 Uhr

  • Das Diagramm hilft eine Tonne! Vielen Dank

    – pavi2410

    28. Juli 2021 um 6:09 Uhr

Benutzeravatar von Sourav Ghosh
Sourav Ghosh

Der Einzeiler: bind() an eigene Adresse, connect() an entfernte Adresse.

Zitat aus der Manpage von bind()

bind() weist die durch addr angegebene Adresse dem Socket zu, auf den der Dateideskriptor sockfd verweist. addrlen gibt die Größe der Adressstruktur in Bytes an, auf die addr zeigt. Traditionell wird dieser Vorgang als “Zuweisen eines Namens zu einem Socket” bezeichnet.

und, aus dem gleichen für connect()

Der Systemaufruf connect() verbindet den Socket, auf den der Dateideskriptor sockfd verweist, mit der durch addr angegebenen Adresse.

Um klarzustellen,

  • bind() ordnet den Socket seiner lokalen Adresse zu [that’s why
    server side binds, so that clients can use that address to connect
    to server.]
  • connect() wird verwendet, um eine Verbindung zu einer Fernbedienung herzustellen [server] Adresse, deshalb Clientseite, verbinden [read as: connect to server] wird genutzt.

  • Also, sagen wir mal, wenn sowohl der Server- als auch der Client-Prozess auf demselben Rechner laufen, können sie dann austauschbar verwendet werden?

    – Siddhartha Ghosh

    19. November 2014 um 10:59 Uhr

  • @SiddharthaGhosh Nein. Vielleicht befinden sich Client und Server auf demselben Computer, aber sie sind es trotzdem sind anderer Prozess, oder? Sowohl die API dient ihrem eigenen Zweck. Sie sind es nie interchangeable

    – Sourav Ghosh

    19. November 2014 um 11:01 Uhr

  • Was genau ist in diesem Zusammenhang mit lokal und remote gemeint?

    – Siddhartha Ghosh

    19. November 2014 um 11:05 Uhr

  • @SiddharthaGhosh local -> der Prozess selbst, remote –> der andere Prozess.

    – Sourav Ghosh

    19. November 2014 um 11:15 Uhr

  • @SouravGhosh, das bedeutet also, dass ich keinen Port angeben kann, an den ich auf der Clientseite binden soll?

    – Hengqi Chen

    7. Januar 2019 um 12:15 Uhr

bind weist den laufenden Prozess an, einen Port zu beanspruchen. dh er sollte sich an Port 80 binden und auf eingehende Anfragen lauschen. Mit bind wird Ihr Prozess zu einem Server. Wenn Sie connect verwenden, weisen Sie Ihren Prozess an, sich mit einem Port zu verbinden, der BEREITS verwendet wird. Ihr Prozess wird zum Kunden. Der Unterschied ist wichtig: bind möchte einen Port, der nicht verwendet wird (damit es ihn beanspruchen und ein Server werden kann), und connect möchte einen Port, der bereits verwendet wird (damit es sich mit ihm verbinden und mit dem Server kommunizieren kann).

Benutzeravatar von pjcard
pjcard

Ich denke, es würde Ihrem Verständnis helfen, wenn Sie daran denken connect() und listen() als Gegenstücke, anstatt connect() und bind(). Der Grund dafür ist, dass Sie anrufen oder auslassen können bind() vorher, obwohl es selten eine gute Idee ist, es vorher anzurufen connect()oder es vorher nicht anzurufen listen().

Wenn es hilft, in Begriffen von Servern und Clients zu denken, ist es das listen() das ist das Markenzeichen der ersteren, und connect() letzteres. bind() kann auf beiden gefunden werden – oder nicht gefunden werden.

Wenn wir davon ausgehen, dass sich Server und Client auf verschiedenen Maschinen befinden, wird es einfacher, die verschiedenen Funktionen zu verstehen.

bind() agiert lokal, bindet also das Ende der Verbindung auf der Maschine, auf der es angerufen wird, an die angeforderte Adresse und weist Ihnen den angeforderten Port zu. Dies geschieht unabhängig davon, ob es sich bei dieser Maschine um einen Client oder einen Server handelt. connect() initiiert von einem Client eine Verbindung zu einem Server, d. h. es stellt eine Verbindung zur angeforderten Adresse und zum Port auf dem Server her. Dieser Server wird mit ziemlicher Sicherheit angerufen haben bind() vor listen()damit Sie wissen, über welche Adresse und welchen Port Sie sich mit ihm verbinden müssen connect().

Wenn Sie nicht anrufen bind()ein Port und eine Adresse werden implizit zugewiesen und an den lokalen Computer gebunden, wenn Sie beides anrufen connect() (Kunde) bzw listen() (Server). Dies ist jedoch ein Nebeneffekt von beiden, nicht ihr Zweck. Ein auf diese Weise zugewiesener Port ist vergänglich.

Ein wichtiger Punkt hierbei ist, dass der Client nicht gebunden werden muss, da Clients eine Verbindung zu Servern herstellen und der Server daher die Adresse und den Port des Clients kennt, obwohl Sie einen kurzlebigen Port verwenden, anstatt sich an etwas Bestimmtes zu binden. Andererseits könnte zwar der Server anrufen listen() ohne anzurufen bind()müssten sie in diesem Szenario ihren zugewiesenen kurzlebigen Port ermitteln und diesen jedem Client mitteilen, mit dem er eine Verbindung herstellen möchte.

Ich nehme an, wie Sie erwähnen connect() Sie interessieren sich für TCP, aber dies überträgt sich auch auf UDP, wo nicht aufgerufen wird bind() vor dem ersten sendto() (UDP ist verbindungslos) bewirkt auch, dass ein Port und eine Adresse implizit zugewiesen und gebunden werden. Eine Funktion, die Sie nicht ohne Bindung aufrufen können, ist recvfrom()die einen Fehler zurückgibt, da es ohne einen zugewiesenen Port und eine gebundene Adresse nichts zu empfangen gibt (oder zu viel, je nachdem, wie Sie das Fehlen einer Bindung interpretieren).

Khans Benutzeravatar
Khan

Aus Wikipedia http://en.wikipedia.org/wiki/Berkeley_sockets#bind.28.29

verbinden():

Der Systemaufruf connect() verbindet einen durch seinen Dateideskriptor identifizierten Socket mit einem entfernten Host, der durch die Adresse dieses Hosts in der Argumentliste angegeben ist.

Bestimmte Arten von Sockets sind verbindungslos, am häufigsten Benutzer-Datagramm-Protokoll-Sockets. Für diese Sockets nimmt connect eine besondere Bedeutung ein: Das Standardziel für das Senden und Empfangen von Daten wird auf die angegebene Adresse gesetzt, was die Verwendung von Funktionen wie send() und recv() auf verbindungslosen Sockets ermöglicht.

connect() gibt eine Ganzzahl zurück, die den Fehlercode darstellt: 0 steht für Erfolg, während -1 einen Fehler darstellt.

binden():

bind() weist einer Adresse einen Socket zu. Wenn ein Socket mit socket() erstellt wird, wird ihm nur eine Protokollfamilie, aber keine Adresse zugewiesen. Diese Zuordnung zu einer Adresse muss mit dem Systemaufruf bind() durchgeführt werden, bevor der Socket Verbindungen zu anderen Hosts akzeptieren kann. bind() nimmt drei Argumente:

sockfd, ein Deskriptor, der den Socket darstellt, an dem die Bindung ausgeführt werden soll. my_addr, ein Zeiger auf eine sockaddr-Struktur, die die Adresse darstellt, an die gebunden werden soll. addrlen, ein socklen_t-Feld, das die Größe der sockaddr-Struktur angibt. Bind() gibt bei Erfolg 0 und -1 zurück, wenn ein Fehler auftritt.

Beispiele: 1.)Mit Connect

#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>

int main(){
  int clientSocket;
  char buffer[1024];
  struct sockaddr_in serverAddr;
  socklen_t addr_size;

  /*---- Create the socket. The three arguments are: ----*/
  /* 1) Internet domain 2) Stream socket 3) Default protocol (TCP in this case) */
  clientSocket = socket(PF_INET, SOCK_STREAM, 0);

  /*---- Configure settings of the server address struct ----*/
  /* Address family = Internet */
  serverAddr.sin_family = AF_INET;
  /* Set port number, using htons function to use proper byte order */
  serverAddr.sin_port = htons(7891);
  /* Set the IP address to desired host to connect to */
  serverAddr.sin_addr.s_addr = inet_addr("192.168.1.17");
  /* Set all bits of the padding field to 0 */
  memset(serverAddr.sin_zero, '\0', sizeof serverAddr.sin_zero);  

  /*---- Connect the socket to the server using the address struct ----*/
  addr_size = sizeof serverAddr;
  connect(clientSocket, (struct sockaddr *) &serverAddr, addr_size);

  /*---- Read the message from the server into the buffer ----*/
  recv(clientSocket, buffer, 1024, 0);

  /*---- Print the received message ----*/
  printf("Data received: %s",buffer);   

  return 0;
}

2.) Bindungsbeispiel:

int main()
{
    struct sockaddr_in source, destination = {};  //two sockets declared as previously
    int sock = 0;
    int datalen = 0;
    int pkt = 0;

    uint8_t *send_buffer, *recv_buffer;

    struct sockaddr_storage fromAddr;   // same as the previous entity struct sockaddr_storage serverStorage;
    unsigned int addrlen;  //in the previous example socklen_t addr_size;
    struct timeval tv;
    tv.tv_sec = 3;  /* 3 Seconds Time-out */
    tv.tv_usec = 0;

    /* creating the socket */         
    if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
        printf("Failed to create socket\n");

    /*set the socket options*/
    setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(struct timeval));

    /*Inititalize source to zero*/
    memset(&source, 0, sizeof(source));       //source is an instance of sockaddr_in. Initialization to zero
    /*Inititalize destinaton to zero*/
    memset(&destination, 0, sizeof(destination));


    /*---- Configure settings of the source address struct, WHERE THE PACKET IS COMING FROM ----*/
    /* Address family = Internet */
    source.sin_family = AF_INET;    
    /* Set IP address to localhost */   
    source.sin_addr.s_addr = INADDR_ANY;  //INADDR_ANY = 0.0.0.0
    /* Set port number, using htons function to use proper byte order */
    source.sin_port = htons(7005); 
    /* Set all bits of the padding field to 0 */
    memset(source.sin_zero, '\0', sizeof source.sin_zero); //optional


    /*bind socket to the source WHERE THE PACKET IS COMING FROM*/
    if (bind(sock, (struct sockaddr *) &source, sizeof(source)) < 0) 
        printf("Failed to bind socket");

    /* setting the destination, i.e our OWN IP ADDRESS AND PORT */
    destination.sin_family = AF_INET;                 
    destination.sin_addr.s_addr = inet_addr("127.0.0.1");  
    destination.sin_port = htons(7005); 

    //Creating a Buffer;
    send_buffer=(uint8_t *) malloc(350);
    recv_buffer=(uint8_t *) malloc(250);

    addrlen=sizeof(fromAddr);

    memset((void *) recv_buffer, 0, 250);
    memset((void *) send_buffer, 0, 350);

    sendto(sock, send_buffer, 20, 0,(struct sockaddr *) &destination, sizeof(destination));

    pkt=recvfrom(sock, recv_buffer, 98,0,(struct sockaddr *)&destination, &addrlen);
    if(pkt > 0)
        printf("%u bytes received\n", pkt);
    }

Ich hoffe, das verdeutlicht den Unterschied

Bitte beachten Sie, dass der von Ihnen deklarierte Socket-Typ davon abhängt, was Sie benötigen. Dies ist äußerst wichtig

Benutzeravatar der Community
Gemeinschaft

Zu lang; Don’t Read: Der Unterschied besteht darin, ob die Quell- (lokale) oder die Zieladresse/Port gesetzt wird. Zusamenfassend, bind() Stellen Sie die Quelle ein und connect() das Ziel festlegen. Egal ob TCP oder UDP.

bind()

bind() legt die lokale (Quell-)Adresse des Sockets fest. Dies ist die Adresse, an der Pakete empfangen werden. Vom Socket gesendete Pakete tragen diese als Quelladresse, sodass der andere Host weiß, wohin er seine Pakete zurücksenden muss.

Wenn Empfang nicht benötigt wird, ist die Socket-Quelladresse nutzlos. Bei Protokollen wie TCP muss der Empfang aktiviert sein, damit sie ordnungsgemäß senden können, da der Zielhost eine Bestätigung zurücksendet, wenn ein oder mehrere Pakete angekommen sind (dh eine Bestätigung).

connect()

  • TCP hat einen “verbundenen” Zustand. connect() löst den TCP-Code aus, um zu versuchen, eine Verbindung zur anderen Seite herzustellen.
  • UDP hat keinen “verbundenen” Zustand. connect() Legen Sie nur eine Standardadresse fest, an die Pakete gesendet werden, wenn keine Adresse angegeben ist. Wann connect() ist nicht benutzt, sendto() oder sendmsg() verwendet werden, die die Zieladresse enthalten.

Wann connect() oder eine Sendefunktion aufgerufen wird und keine Adresse gebunden ist, bindet Linux den Socket automatisch an einen zufälligen Port. Technische Details finden Sie unter inet_autobind() im Linux-Kernel-Quellcode.

Nebenbemerkungen

  • listen() ist nur TCP.
  • Im AF_INET Familie, die Quell- oder Zieladresse des Sockets (struct sockaddr_in) besteht aus einer IP-Adresse (vgl IP-Header) und TCP- oder UDP-Port (siehe TCP und UDP Header).

1424570cookie-checksocket connect() vs bind()

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy