2013-05-04 10 views
5

मैं एक छोटा सी क्लाइंट/सर्वर एप्लिकेशन लिख रहा हूं, लेकिन बाहरी आईपी पते का उपयोग करते समय मैं कनेक्शन काम नहीं कर सकता। दोनों क्लाइंट और सर्वर के लिए कोड here से लिया जाता है, विशेष रूप से ग्राहकों को कार्य करें:बाह्य आईपी का उपयोग कर सर्वर से कनेक्ट करने के लिए getaddrinfo का उपयोग कैसे करें?

char *default_server_name = "localhost"; 
    char *server_name = NULL; 
    int nport = DEFAULT_DAMA_PORT; 
    char port[15]; 

    // Parse the command line options 
    if (parse_options(argc, argv, &server_name, &nport) < 0) { 
     return -1; 
    } 

    if (server_name == NULL) { 
     server_name = default_server_name; 
    } 

    snprintf(port, 15, "%d", nport); 

    // Connect to the server 
    int client_socket; 
    struct addrinfo hints, *servinfo, *p; 
    int rv; 

    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    if ((rv = getaddrinfo(server_name, port, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     exit(1); 
    } 

    for (p=servinfo; p != NULL; p = p->ai_next) { 
     if ((client_socket = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { 
#ifdef DEBUG 
      perror("socket"); 
#endif 
      continue; 
     } 

     if (connect(client_socket, p->ai_addr, p->ai_addrlen) == -1) { 
      close(client_socket); 
#ifdef DEBUG 
      perror("connect"); 
#endif 
      continue; 
     } 

     // Connected succesfully! 
     break; 
    } 

    if (p == NULL) { 
     // The loop wasn't able to connect to the server 
     fprintf(stderr, "Couldn't connect to the server\n."); 
     exit(1); 
    } 

सर्वर जबकि:

int nport; 
    char port[15]; 
    if (parse_options(argc, argv, &nport) < 0) { 
     return -1; 
    } 

    snprintf(port, 15, "%d", nport); 

    int server_socket; 
    struct addrinfo hints, *servinfo, *p; 
    int rv; 

    memset(&hints, 0, sizeof(hints)); 
    hints.ai_family = AF_UNSPEC; 
    hints.ai_socktype = SOCK_STREAM; 
    hints.ai_flags = AI_PASSIVE; 

    if ((rv = getaddrinfo(NULL, port, &hints, &servinfo)) != 0) { 
     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv)); 
     exit(1); 
    } 

    for (p=servinfo; p != NULL; p = p->ai_next) { 
     if ((server_socket = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == -1) { 
#ifdef DEBUG 
      perror("socket"); 
#endif 
      continue; 
     } 

     if (bind(server_socket, p->ai_addr, p->ai_addrlen) == -1) { 
      close(server_socket); 
#ifdef DEBUG 
      perror("bind"); 
#endif 
      continue; 
     } 

     // We binded successfully! 
     break; 
    } 

    if (p == NULL) { 
     fprintf(stderr, "failed to bind socket\n"); 
     exit(2); 
    } 

    int pl_one, pl_two; 
    socklen_t pl_one_len, pl_two_len; 
    struct sockaddr_in pl_one_addr, pl_two_addr; 

    if (listen(server_socket, 2) < 0) { 
     fatal_error("Error in syscall listen.", 2); 
    } 

    // Get the two clients connections. 
    pl_one_len = sizeof(pl_one_addr); 
    pl_one = accept(server_socket, 
        (struct sockaddr *)&pl_one_addr, 
        &pl_one_len); 
    if (pl_one < 0) { 
     fatal_error("Error in syscall accept.", 3); 
    } 

    pl_two_len = sizeof(pl_two_addr); 
    pl_two = accept(server_socket, 
        (struct sockaddr *)&pl_two_addr, 
        &pl_two_len); 
    if (pl_two < 0) { 
     fatal_error("Error in syscall accept.", 3); 
    } 

अगर मैं आदेश पंक्ति में मेरी मशीन का IP निर्दिष्ट करें, और इसलिए ग्राहकों में server_name151.51.xxx.xxx जैसी स्ट्रिंग पर सेट है, तो सॉकेट सर्वर से कनेक्ट नहीं हो सकते हैं।

होस्ट नाम है कि आप में रुचि रखते हैं nodename पैरामीटर में चला जाता है: इसके अलावा 127.0.0.1 का उपयोग कर एक ही व्यवहार है, जो मुझे लगता है कि जब प्रलेखन राज्यों में आता है पता चलता है। पता या तो होस्ट नाम हो सकता है, जैसे "www.example.com", या एक आईपीवी 4 या आईपीवी 6 पता (एक स्ट्रिंग के रूप में पारित)।

यह सिर्फ मजाक कर रहा है।

क्या मैं कुछ गलत तरीके से कर रहा हूं? क्या फ़ायरवॉल इत्यादि के साथ कुछ समस्या हो सकती है जो ग्राहकों को आईपी पते का उपयोग करके कनेक्ट करने से रोक रही है?

नोट: मैं पहले से ही इस समस्या के लिए एक बहुत खोज की है और कुछ लोगों को बिल्कुल भी getaddrinfo का उपयोग कर से बचने के लिए और सीधे INADDR_ANY से भरना कहते हैं, लेकिन getaddrinfo प्रलेखन कहा गया है कि गुजर NULL के रूप में पहले से ही nodenameINADDR_ANY साथ पता भरना चाहिए, तो मुझे नहीं पता कि जब मैं इसे स्वचालित रूप से करता हूं तो मुझे पुरानी विधि का उपयोग क्यों करना चाहिए।

+0

सर्वर भाग के लिए अपेक्षित कार्य करने के लिए (कनेक्शन स्वीकार करने में सक्षम होने के लिए) आपको 'श्रवण()' और 'स्वीकार()' पर कॉल जोड़ना होगा। आप अध्याय 9.15 और अध्याय 9.1 पर पढ़ना पसंद कर सकते हैं। – alk

+0

@alk मैं स्पष्ट रूप से 'सुन' और 'स्वीकार' करने के लिए कॉल करता हूं (अन्यथा क्लाइंट कैसे काम करता है यदि क्लाइंट 'localhost'' server_name' के रूप में उपयोग करता है?)। मैं वैसे भी उन्हें प्रश्न में जोड़ दूंगा। – Bakuriu

+2

क्या राउटर के पीछे सर्वर है? क्या आवश्यक बंदरगाह खोले या अग्रेषित किए गए हैं? – typ1232

उत्तर

1

टिप्पणियों में लिखे गए अनुसार आप राउटर के पीछे किसी नेटवर्क में स्थित सर्वर से कनेक्ट करने का प्रयास कर रहे हैं।

127.0.0.1 या localhost ऑपरेटिंग सिस्टम की रीडायरेक्शन हैं और राउटर पर नहीं जाएंगे। यही कारण है कि यह आपके लिए काम किया।

यदि आप बाहरी आईपी पता निर्दिष्ट करते हैं, तो कनेक्शन राउटर के माध्यम से किया जाता है और आपके द्वारा उपयोग किए जाने वाले बंदरगाहों को राउटर कॉन्फ़िगरेशन में अग्रेषित करने की आवश्यकता होती है। किसी भी सामान्य होम इंटरनेट एंड यूजर राउटर डिफ़ॉल्ट रूप से किसी भी पोर्ट से आने वाले कनेक्शन ब्लॉक करता है।

संबंधित मुद्दे