सॉकेट कनेक्ट () बनाम बाइंड ()


121

दोनों connect()और bind()सिस्टम एक पते (आमतौर पर एक आईपी / पोर्ट संयोजन) के लिए सॉकेट फ़ाइल डिस्क्रिप्टर को 'सहयोगी' कहते हैं। उनके प्रोटोटाइप इस प्रकार हैं: -

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

तथा

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

2 कॉल के बीच सटीक अंतर क्या है? कब connect()और किसका उपयोग करना चाहिए bind()?

विशेष रूप से, कुछ नमूना सर्वर क्लाइंट कोड में, पाया गया कि क्लाइंट उपयोग कर रहा है connect()और सर्वर bind()कॉल का उपयोग कर रहा है । कारण मेरे लिए पूरी तरह से स्पष्ट नहीं था।


19
एक वाक्य में: बाइंड स्थानीय पते पर है, कनेक्ट दूरस्थ पते के लिए है।
SHR

जवाबों:


230

समझ को बेहतर बनाने के लिए, यह पता लगाने की सुविधा देता है कि वास्तव में कहाँ बाँधें और कनेक्ट करें,

सौरव द्वारा स्पष्ट किए गए दो कॉल की स्थिति के लिए आगे,

bind () सॉकेट को उसके स्थानीय पते के साथ संबद्ध करता है [इसीलिए सर्वर साइड बांधता है, ताकि क्लाइंट उस पते का उपयोग सर्वर से कनेक्ट करने के लिए कर सकें।] () दूरस्थ (सर्वर) पते से कनेक्ट करने के लिए उपयोग किया जाता है, इसीलिए क्लाइंट साइड है , कनेक्ट [के रूप में पढ़ा: सर्वर से कनेक्ट] का उपयोग किया जाता है।

विशिष्ट भूमिकाओं और संगत कार्यान्वयन के कारण हम उनका उपयोग परस्परता से नहीं कर सकते (तब भी जब हमारे पास एक ही मशीन पर क्लाइंट / सर्वर हो)।

मैं इन कॉल टीसीपी / आईपी हैंडशेक को सहसंबंधित करने की सिफारिश करूंगा।

यहाँ छवि विवरण दर्ज करें

तो, जो SYN को यहां भेजेगा, वह कनेक्ट () होगा। जबकि बाइंड () का उपयोग संचार अंत बिंदु को परिभाषित करने के लिए किया जाता है।

उम्मीद है की यह मदद करेगा!!


1
धन्यवाद भाई। आरेख के साथ सब कुछ तेजी से समझ सकता है। क्या आप बता सकते हैं कि यहाँ क्या अंतर है, अगर हम udp का उपयोग कर रहे हैं?
एपम

8
स्वीकार () <br> को नीचे ले जाया जाना चाहिए <br> क्लाइंट से कनेक्शन तक ब्लॉक करें
tschodt

मुझे लगता है कि एक p2p नेटवर्क में एक नेटवर्क में सभी नोड्स को बाइंड का उपयोग करना चाहिए, क्या मैं सही हूं?
कपिल

46

एक लाइनर: bind() खुद के पते के लिए, connect()दूरदराज के पते पर।

के मैन पेज से उद्धरण bind()

bind () फ़ाइल डिस्क्रिप्टर sockfd द्वारा निर्दिष्ट सॉकेट में Addr द्वारा निर्दिष्ट पते को निर्दिष्ट करता है। addrlen आकार को निर्दिष्ट करता है, बाइट में, पता संरचना का addr द्वारा इंगित किया गया है। परंपरागत रूप से, इस ऑपरेशन को "सॉकेट के लिए एक नाम निर्दिष्ट करना" कहा जाता है।

और, उसी के लिए connect()

कनेक्ट () सिस्टम कॉल फ़ाइल डिस्क्रिप्टर sockfd द्वारा निर्दिष्ट सॉकेट को Addr द्वारा निर्दिष्ट पते से जोड़ता है।

स्पष्टीकरण देना,

  • bind()सॉकेट को उसके स्थानीय पते के साथ संबद्ध करता है [इसीलिए सर्वर साइड binds, ताकि क्लाइंट उस पते का उपयोग सर्वर से कनेक्ट करने के लिए कर सकें]।
  • connect() का उपयोग दूरस्थ [सर्वर] पते से कनेक्ट करने के लिए किया जाता है, इसीलिए ग्राहक पक्ष, कनेक्ट [के रूप में पढ़ें: सर्वर से कनेक्ट करें] का उपयोग किया जाता है।

तो, कहते हैं, यदि सर्वर और क्लाइंट प्रक्रिया दोनों एक ही मशीन पर चलती हैं, तो क्या उनका उपयोग परस्पर किया जा सकता है?
सिद्धार्थ घोष

1
@SiddharthaGhosh नहीं। हो सकता है कि ग्राहक और सर्वर एक ही मशीन पर हों, लेकिन फिर भी वे अलग - अलग प्रक्रिया में हैं, है ना? दोनों एपीआई अपने स्वयं के विद्यार्थियों की सेवा करते हैं। वे कभी नहीं हैंinterchangeable
सौरव घोष

इस संदर्भ में स्थानीय और दूरस्थ का क्या मतलब है?
सिद्धार्थ घोष

@SiddharthaGhosh local-> स्वयं प्रक्रिया, remote-> अन्य प्रक्रिया।
सौरव घोष

@SouravGhosh तो इसका मतलब है कि मैं क्लाइंट की तरफ से बांधने के लिए पोर्ट निर्दिष्ट नहीं कर सकता?
हेंगकी चेन

12

bind एक पोर्ट का दावा करने के लिए रनिंग प्रक्रिया को बताता है। यानी, यह खुद को 80 पोर्ट करने के लिए बाध्य करना चाहिए और इनकमिंग अनुरोधों को सुनना चाहिए। बाइंड के साथ, आपकी प्रक्रिया एक सर्वर बन जाती है। जब आप कनेक्ट का उपयोग करते हैं, तो आप एक पोर्ट से कनेक्ट होने के लिए अपनी प्रक्रिया बताते हैं जो उपयोग में है। आपकी प्रक्रिया एक ग्राहक बन जाती है। अंतर महत्वपूर्ण है: बाइंड एक ऐसा पोर्ट चाहता है जो उपयोग में न हो (ताकि यह दावा कर सके और सर्वर बन जाए), और कनेक्ट एक ऐसा पोर्ट चाहता है जो पहले से उपयोग में है (इसलिए यह इसे कनेक्ट कर सकता है और सर्वर से बात कर सकता है)


9

विकिपीडिया से http://en.wikipedia.org/wiki/Berkeley_sockets#bind.28.29 से

जुडिये():

कनेक्ट () सिस्टम कॉल एक सॉकेट को जोड़ता है, जिसे इसकी फ़ाइल डिस्क्रिप्टर द्वारा पहचाना जाता है, तर्क सूची में उस होस्ट के पते द्वारा निर्दिष्ट दूरस्थ होस्ट के लिए।

कुछ प्रकार की सॉकेट्स कनेक्शन रहित होती हैं, आमतौर पर उपयोगकर्ता डेटाग्राम प्रोटोकॉल सॉकेट्स। इन सॉकेट्स के लिए, कनेक्ट एक विशेष अर्थ में होता है: डेटा भेजने और प्राप्त करने के लिए डिफ़ॉल्ट लक्ष्य दिए गए पते पर सेट हो जाता है, कनेक्शन रहित सॉकेट्स पर भेजने () और recv () जैसे कार्यों का उपयोग करने की अनुमति देता है।

कनेक्ट () त्रुटि कोड का प्रतिनिधित्व करने वाला पूर्णांक देता है: 0 सफलता का प्रतिनिधित्व करता है, जबकि -1 त्रुटि का प्रतिनिधित्व करता है।

बाँध ():

bind () एक पते पर एक सॉकेट देता है। जब सॉकेट () का उपयोग करके एक सॉकेट बनाया जाता है, तो इसे केवल एक प्रोटोकॉल परिवार दिया जाता है, लेकिन एक पता नहीं सौंपा जाता है। एक पते के साथ इस जुड़ाव को अन्य मेजबानों से कनेक्शन स्वीकार करने से पहले बाइंड () सिस्टम कॉल के साथ किया जाना चाहिए। बाइंड () तीन तर्क देता है:

sockfd, एक डिस्क्रिप्टर जिस पर बांधने के लिए सॉकेट का प्रतिनिधित्व करता है। my_addr, एक sockaddr संरचना के लिए एक सूचक जो बाइंड करने के लिए पते का प्रतिनिधित्व करता है। Addrlen, sockaddr संरचना के आकार को निर्दिष्ट करने वाला एक socklen_t क्षेत्र। यदि त्रुटि होती है, तो बाइंड () रिटर्न 0 और -1 पर होता है।

उदाहरण: 1.) कनेक्ट का उपयोग करना

#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.) बाइंड उदाहरण:

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);
    }

मुझे उम्मीद है कि अंतर स्पष्ट करता है

कृपया ध्यान दें कि आपके द्वारा घोषित सॉकेट प्रकार इस बात पर निर्भर करेगा कि आपको क्या चाहिए, यह अत्यंत महत्वपूर्ण है


9

मुझे लगता है कि यह आपकी समझ में मदद करेगा यदि आप connect()और के listen()बजाय समकक्षों के बारे में सोचते हैं connect()और bind()। इसका कारण यह है कि आप या bind()तो पहले कॉल कर सकते हैं या छोड़ सकते हैं, हालांकि यह शायद ही कभी पहले कॉल करने के लिए एक अच्छा विचार है connect(), या पहले इसे कॉल करने के लिए नहीं listen()

यदि यह सर्वर और क्लाइंट के संदर्भ में सोचने में मदद करता है, तो यह listen()पूर्व और connect()बाद की पहचान है। bind()पाया जा सकता है - या नहीं मिला - या तो।

यदि हम मानते हैं कि हमारा सर्वर और क्लाइंट विभिन्न मशीनों पर हैं, तो विभिन्न कार्यों को समझना आसान हो जाता है।

bind()स्थानीय रूप से कार्य करता है, जो यह कहना है कि यह उस मशीन पर कनेक्शन के अंत को बांधता है जिस पर इसे अनुरोधित पते पर कहा जाता है, और आपके लिए अनुरोधित पोर्ट असाइन करता है। यह इस बात की परवाह किए बिना करता है कि वह मशीन एक ग्राहक या सर्वर होगी। connect()एक सर्वर से एक कनेक्शन शुरू करता है, जो यह कहना है कि यह क्लाइंट से अनुरोधित पते और सर्वर पर पोर्ट से जुड़ता है। यही कारण है कि सर्वर लगभग निश्चित रूप से कहा जाता है जाएगा bind()से पहले listen(), क्रम में आप को पता है, जिस पर पता और पोर्ट उपयोग करने के साथ यह करने के लिए कनेक्ट करने में सक्षम होने के लिए connect()

यदि आप कॉल नहीं करते हैं bind(), तो एक पोर्ट और पता आपके द्वारा connect()(क्लाइंट) या listen()(सर्वर) कॉल करने पर आपके लिए स्थानीय मशीन पर असाइन किया जाएगा और बाध्य किया जाएगा । हालांकि, यह दोनों का साइड इफेक्ट है, न कि उनका उद्देश्य। इस तरह से असाइन किया गया एक पोर्ट पंचांग है।

यहां एक महत्वपूर्ण बिंदु यह है कि क्लाइंट को बाध्य होने की आवश्यकता नहीं है, क्योंकि क्लाइंट सर्वर से जुड़ते हैं, और इसलिए सर्वर को क्लाइंट के पते और पोर्ट का पता चल जाएगा, भले ही आप किसी विशिष्ट चीज़ को बाध्य करने के बजाय एक अल्पकालिक पोर्ट का उपयोग कर रहे हों। दूसरी ओर, हालांकि सर्वर listen()बिना कॉल किए कॉल कर सकता है bind(), उस स्थिति में उन्हें अपने निर्दिष्ट एपेरमल पोर्ट को खोजने की आवश्यकता होगी, और किसी भी क्लाइंट से यह संवाद करना होगा कि वह इसे कनेक्ट करना चाहता है।

मुझे लगता है कि जैसा कि आप उल्लेख connect()करते हैं कि आप टीसीपी में रुचि रखते हैं, लेकिन यह यूडीपी को भी वहन करता है, जहां bind()पहले sendto()(यूडीपी कनेक्शन-कम है) से पहले कॉल नहीं किया जाता है, यह भी एक बंदरगाह और पते का कारण बनता है जिसे अंतर्निहित रूप से सौंपा और बाध्य किया जाता है। एक फ़ंक्शन जिसे आप बाइंडिंग के बिना कॉल नहीं कर सकते हैं recvfrom(), जो एक त्रुटि लौटाएगा, क्योंकि एक निर्धारित पोर्ट और बाउंड एड्रेस के बिना, (या बहुत अधिक से, आप किसी बंधन की अनुपस्थिति की व्याख्या कैसे करते हैं) के आधार पर प्राप्त करने के लिए कुछ भी नहीं है।


1

बहुत लंबा; न पढ़ें: अंतर यह है कि स्रोत (स्थानीय) या गंतव्य पता / पोर्ट सेट किया जा रहा है या नहीं। संक्षेप में, bind()स्रोत connect()सेट करें और गंतव्य सेट करें। भले ही टीसीपी या यूडीपी हो।

bind()

bind()सॉकेट का स्थानीय (स्रोत) पता सेट करें। यह वह पता है जहां पैकेट प्राप्त होते हैं। सॉकेट द्वारा भेजे गए पैकेट इसे स्रोत पते के रूप में ले जाते हैं, इसलिए दूसरे मेजबान को पता चल जाएगा कि उसके पैकेट को वापस कहां भेजना है।

यदि प्राप्त करने की आवश्यकता नहीं है तो सॉकेट स्रोत का पता बेकार है। टीसीपी जैसे प्रोटोकॉल को ठीक से भेजने के लिए सक्षम प्राप्त करने की आवश्यकता होती है, क्योंकि गंतव्य होस्ट एक पुष्टिकरण भेजते हैं जब एक या अधिक पैकेट आ गए हैं (यानी पावती)।

connect()

  • टीसीपी में एक "जुड़ा हुआ" राज्य है। connect()दूसरी तरफ कनेक्शन स्थापित करने का प्रयास करने के लिए टीसीपी कोड को ट्रिगर करता है।
  • यूडीपी का कोई "कनेक्टेड" राज्य नहीं है। connect()जब कोई पता निर्दिष्ट नहीं किया जाता है तो केवल एक डिफ़ॉल्ट पता सेट करें जहां पैकेट भेजे जाते हैं। जब connect()उपयोग नहीं किया जाता है, sendto()या sendmsg()गंतव्य पते के साथ उपयोग किया जाना चाहिए।

जब connect()कोई फ़ंक्शन भेजा जाता है, और कोई पता नहीं चलता है, तो लिनक्स स्वचालित रूप से सॉकेट को एक यादृच्छिक पोर्ट से बांधता है। तकनीकी विवरण के लिए, inet_autobind()लिनक्स कर्नेल स्रोत कोड पर एक नज़र डालें ।

साइड नोट्स

  • listen() केवल टीसीपी है।
  • में AF_INET परिवार, सॉकेट के स्रोत या गंतव्य पता ( struct sockaddr_in) को IP पते द्वारा रचित है (देखें IP हेडर ), और TCP या UDP पोर्ट (देखें टीसीपी और यूडीपी हेडर)।
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.