2014-11-19 19 views
66

Sowohl connect() als auch bind() Systemaufrufe "verknüpfen" den Socket-Dateideskriptor mit einer Adresse (normalerweise eine IP/Port-Kombination). Ihre Prototypen sind wie: -Socket connect() vs bind()

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 zwei Anrufen? Wann sollte man connect() und wann bind() verwenden?

Speziell in einigen Client-Beispielserverclients wurde festgestellt, dass der Client connect() verwendet und der Server den Aufruf bind() verwendet. Der Grund war mir nicht völlig klar.

+8

In einem Satz: bind ist an lokale Adresse, Verbindung ist an Remote-Adresse. – SHR

Antwort

126

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

Weiteres zur Positionierung von zwei Anrufen, wie Sourav geklärt,

bind() ordnet die Buchse mit seiner lokalen Adresse [deshalb serverseitig bindet, so dass Clients diese Adresse verwenden können, um eine Verbindung zum Server herzustellen.] connect() wird verwendet, um eine Verbindung zu einer fernen [Server] -Adresse herzustellen, deshalb clientseitig, connect [read as : Verbindung zum Server herstellen] wird verwendet.

Wir können sie nicht austauschbar verwenden (auch wenn wir Client/Server auf derselben Maschine haben) wegen der spezifischen Rollen und der entsprechenden Implementierung.

Ich werde weiter empfehlen, diese Anrufe TCP/IP-Handshake korrelieren.

enter image description here

Also, wer SYN hier senden wird, wird es() verbinden. Während bind() zum Definieren des Kommunikationsendpunkts verwendet wird.

Hoffe das hilft !!

+0

danke bro. Mit dem Diagramm kann sich alles schnell verziehen. Können Sie sagen, was ist der Unterschied hier, wenn wir UDP verwenden? – apm

+6

accept()
sollte unter
Block bis Verbindung vom Client verschoben werden – tschodt

24

Der eine Liner:bind() zu eigene Adresse, connect() zu remote Adresse.

Zitiert aus der man-Seite von bind()

bind() weist die Adresse von addr an die Buchse durch den Dateideskriptor sockfd bezeichnet angegeben. addrlen gibt die Größe der Adressstruktur in Byte an, auf die addr verweist. Traditionell wird diese Operation als "Zuweisung eines Namens zu einem Socket" bezeichnet.

und aus derselben für connect()

Das connect verbindet() den Systemaufruf an Deskriptor bezeichnet Buchse durch die Datei an den durch addr spezifizierten Adresse sockfd.

Um zu klären,

  • bind() ordnet die Buchse mit seiner lokalen Adresse [deshalb Server-Seite bind s, so dass die Kunden diese Adresse verwenden können Verbindung zum Server.]
  • connect() wird verwendet, um eine Verbindung zu einer entfernten [Server] -Adresse herzustellen, das ist Warum ist Client-Seite, verbinden [lesen als: mit Server verbinden] verwendet wird.
+0

Also, wenn der Server- und der Client-Prozess auf demselben Computer ausgeführt werden, können sie dann synonym verwendet werden? –

+0

@SiddharthaGhosh Nr. Vielleicht Client und Server sind auf der gleichen Maschine, aber immer noch ** sind ** unterschiedliche Verfahren, nicht wahr? Beide API-Dienste sind ein eigenes Programm. Sie sind niemals "austauschbar". –

+0

Was ist in diesem Zusammenhang genau mit lokal und fern gemeint? –

4

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

connect():

Die connect() Systemaufruf verbindet eine Buchse, durch seinen Dateideskriptor identifiziert, auf eine Remote-Host, durch die für Host-Adresse in der angegebenen Argumentliste.

Bestimmte Arten von Sockets sind verbindungslos, am häufigsten Benutzer Datagramm-Protokoll-Sockets. Für diese Sockets hat connect eine besondere Bedeutung: Das Standardziel für das Senden und Empfangen von Daten wird auf die angegebene Adresse gesetzt, so dass Funktionen wie send() und recv() auf verbindungslosen Sockets verwendet werden können.

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

bind():

bind() weist eine Buchse auf eine Adresse. Wenn ein Socket mit socket() erstellt wird, erhält er nur eine Protokollfamilie, aber keine Adresse. Diese Zuordnung zu einer Adresse muss mit dem Systemaufruf bind() erfolgen, bevor der Socket Verbindungen zu anderen Hosts akzeptieren kann. bind() benötigt drei Argumente:

sockfd, ein Deskriptor, der den Socket zum Ausführen der Bindung darstellt. my_addr, ein Zeiger auf eine Sockaddr-Struktur, die die zu bindende Adresse darstellt. addrlen, ein socklen_t-Feld, das die Größe der Sockaddr-Struktur angibt. Bind() gibt 0 bei Erfolg 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.) Bind Beispiel:

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, dass die Differenz

EDIT stellt klar: Bitte beachten Sie, dass die Buchse Typ, den Sie angeben, hängt davon ab, was Sie benötigen, das ist extrem wichtig

4

bind teilt dem laufenden Prozess mit, einen Port zu beanspruchen. d. h., es sollte sich an den Port 80 binden und auf eingehende Anfragen warten. Mit bind wird Ihr Prozess zu einem Server. Wenn Sie connect verwenden, weisen Sie Ihren Prozess an, eine Verbindung zu einem bereits verwendeten Port herzustellen. Ihr Prozess wird zum Kunden. Der Unterschied ist wichtig: bind will einen Port, der nicht benutzt wird (damit er ihn beanspruchen kann und ein Server wird), und connect möchte einen Port, der bereits benutzt wird (damit er sich damit verbinden und mit dem Server sprechen kann)

1

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

Wenn es hilft, in Bezug auf Server und Clients zu denken, ist es listen(), das ist das Markenzeichen des ehemaligen und connect() letzteres. bind() kann entweder gefunden oder nicht gefunden werden.

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

bind() wirkt lokal, dh bindet das Ende der Verbindung auf der Maschine, auf der es aufgerufen wird, an die angeforderte Adresse und weist Ihnen den angeforderten Port zu. Dies geschieht unabhängig davon, ob diese Maschine ein Client oder ein Server ist. connect() initiiert eine Verbindung zu einem Server, dh es verbindet sich mit der angeforderten Adresse und dem Port auf dem Server von einem Client. Dieser Server wird mit ziemlicher Sicherheit bind() vor listen() aufgerufen haben, damit Sie wissen können, an welche Adresse und an welchen Port er sich unter Verwendung von connect() angeschlossen hat.

Wenn Sie nicht bind() nennen, ein Port und Adresse wird implizit für Sie auf dem lokalen Computer zugeordnet und gebunden werden, wenn Sie anrufen entweder connect() (Client) oder listen() (Server). Dies ist jedoch ein Nebeneffekt von beiden, nicht deren Zweck. Ein auf diese Weise zugewiesener Port ist kurzlebig.

Ein wichtiger Punkt hier ist, dass der Client nicht gebunden werden muss, da Clients eine Verbindung zu Servern herstellen und der Server die Adresse und den Port des Clients erkennt, obwohl Sie einen ephemeren Port verwenden Bindung an etwas Bestimmtes. Auf der anderen Seite, obwohl der Server listen() ohne Aufruf von bind() aufrufen könnte, müssten sie in diesem Szenario ihren zugewiesenen ephemeren Port ermitteln und dies jedem Client mitteilen, mit dem er eine Verbindung herstellen möchte.

Ich gehe davon aus, wie Sie erwähnen connect() Sie in TCP interessiert sind, aber dies trägt auch über UDP, wo nicht bind() vor dem ersten Aufruf sendto() (UDP ist verbindungslose) auch einen Port und Adresse bewirkt implizit zugewiesen werden und gebunden. Eine Funktion, die Sie ohne Bindung nicht aufrufen können, ist recvfrom(), die einen Fehler zurückgibt, da ohne einen zugewiesenen Port und eine gebundene Adresse nichts zu empfangen ist (oder zu viel, je nachdem, wie Sie das Fehlen einer Bindung interpretieren).