2012-01-03 18 views
10

सॉकेट प्रोग्रामिंग एपीआई का उपयोग करना (उदा।, सॉकेट(), कनेक्ट(), स्वीकार करें() ...), मुझे कैसे पता चलेगा कि एक टीसीपी कनेक्शन एक ही मशीन पर दो प्रक्रियाओं के बीच है या नहीं? कहें, मेरे पास सॉकेट फ़ाइल डिस्क्रिप्टर है, और रिमोट आईपी है। क्या मैं बस निरीक्षण कर सकता हूं कि रिमोट आईपी 127.0.0.1 है या नहीं?कैसे पता चलेगा कि एक टीसीपी कनेक्शन एक ही मशीन पर दो प्रक्रियाओं के बीच है?

+1

आप एक ही सॉकेट पर बुला 'getsockname()' और 'getpeername()' तो तुलना पतों लौटे कोशिश कर सकते हैं। –

+0

एक ही मशीन पर कई नेटवर्क उपकरणों को छोड़कर, क्या आप कनेक्शन के प्रत्येक छोर पर मैक पता देख पाएंगे, और देखें कि वे समान हैं या नहीं? – abelenky

+0

आमतौर पर कोई मैक हेडर नहीं होता है, और इसलिए कोई मैक पता नहीं है, जो लूपबैक पर उपयोग किया जाता है। –

उत्तर

2

यहां मैंने जिस दृष्टिकोण का उपयोग किया है, वह यहां है। विचार है कि उस आईपी पते पर श्रोता को बांधने का प्रयास करें और यह तय करने के लिए विफलता/सफलता कोड का उपयोग करें कि पता स्थानीय है या नहीं।

मैं दावा नहीं कर रहा हूं कि यह विशेष रूप से कुशल है, लेकिन यह काफी विश्वसनीय होना चाहिए, और मेरे आवेदन के लिए यह उचित था।

#include <sys/socket.h> 
#include <errno.h> 
/* ...probably need some other headers I am forgetting... */ 

int 
is_local(const struct sockaddr *addr, socklen_t addr_len) 
{ 
    const char *func = "is_local()"; 
    int result = 0; 

    int tmp = socket(addr->sa_family, SOCK_STREAM, 0); 
    if (tmp < 0) { 
     printf("%s: socket(%d,SOCK_STREAM,0) failed, errno %d\n", 
       func, addr->sa_family); 

     goto out; 
    } 

    /* If bind() succeeds, or if it fails because the address is in 
     use, then the address must be local to this system. */ 
    if (bind(tmp, addr, addr_len) < 0) { 
     if (errno == EADDRINUSE) 
      result = 1; 
     else if (errno == EADDRNOTAVAIL) 
      ; /* do nothing; address is remote */ 
     else 
      printf("%s: bind() unexpected error %d\n", func, errno); 
    } 
    else { 
     result = 1; 
    } 

    close(tmp); 

out: 
    return result; 
} 

आप इसे इस तरह कहते हैं:

struct sockaddr_storage client_addr; 
socklen_t client_addr_len = sizeof(client_addr); 
int fd = accept(listener, &client_addr, &client_addr_len); 

if (is_local((struct sockaddr *)&client_addr, client_addr_len)) 
    /* peer is local */ 
+0

मुझे यह दृष्टिकोण पसंद है! – flyingbin

7

यह निर्धारित करने के लिए कोई वास्तव में विश्वसनीय तरीका नहीं है - आप एक विश्व स्तर पर कराई आईपी पते (यानी, स्थानीय प्रक्रियाओं 127.0.0.1 के अलावा अन्य आईपी उपयोग कर सकते हैं) का उपयोग कर स्थानीय प्रक्रियाओं से जुड़ सकते हैं। यदि आप वर्चुअलाइज्ड वातावरण में हैं, तो एक ही भौतिक हार्डवेयर पर एक अलग वर्चुअल मशीन में चलने की प्रक्रिया के लिए भी संभव है।

हालांकि, ध्यान दें कि यदि दूरस्थ आईपी (getpeername के माध्यम से) या (getsockname के माध्यम से) स्थानीय IP 127 (127.0.0.1 सहित) के साथ शुरू होता है, तो यह वास्तव में एक स्थानीय कनेक्शन है, हालांकि, आप इस संभावना से इंकार नहीं कर सकते कि स्थानीय कनेक्शन हो सकता है यदि यह पते की एक अलग जोड़ी है।

2

यदि आपके पास पहले से ही रिमोट आईपी पता है, तो आप जांच सकते हैं कि यह लूपबैक पता है या नहीं, यदि यह मेजबान का आईपी पता है, क्योंकि, जैसा कि सिनीकर बताता है, इसे लूपबैक से अधिक नहीं होना चाहिए एक स्थानीय कनेक्शन होने के लिए पता।

3

उपयोग getsockname() और getpeername() कनेक्शन से संबंधित दो आईपी नहीं निकाला जा, तो (GetAdaptersInfo() और GetAdapterAddresses() विंडोज पर की तरह या अन्य प्लेटफ़ॉर्म-विशिष्ट एपीआई,) gethostname() और gethostbyname() का उपयोग आईपी स्थानीय मशीन के हैं निर्धारित करने के लिए है, तो आप स्थानीय आईपी से कनेक्शन आईपी की तुलना कर सकते हैं यह देखने के लिए कि क्या वे दोनों मेल खाते हैं। एक मशीन में कई आईपी असाइन किए जा सकते हैं, और एक ही मशीन पर कई आईपी एक-दूसरे के साथ संवाद कर सकते हैं।

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