2009-03-02 9 views
10

यदि कोई सॉकेट IN6ADDR_ANY या INADDR_ANY से जुड़ा हुआ है और आप सॉकेट पर संदेश प्राप्त करने के लिए recvfrom() जैसे कॉल का उपयोग करते हैं। क्या यह पता लगाने का कोई तरीका है कि संदेश किस इंटरफ़ेस से आया था?कैसे बताएं कि सॉकेट को किस इंटरफ़ेस से संदेश प्राप्त हुआ?

आईपीवी 6 लिंक-स्कोप संदेशों के मामले में, मुझे उम्मीद थी कि recvfrom() के तर्क से scope_id फ़ील्ड इंटरफ़ेस आईडी में प्रारंभ होगा। दुर्भाग्यवश यह मेरे परीक्षण कार्यक्रम में 0 पर सेट है।

कोई भी इस जानकारी को जानने के लिए किसी तरीके से जानता है?

उत्तर

3

प्रत्येक इंटरफ़ेस को बाध्य करने के अलावा, मुझे आईपीवी 4, प्रति से एक तरीके से अवगत नहीं है।

आईपीवी 6 ने इस कमी को हल करने के लिए आईपीवी 6_PKTINFO सॉकेट विकल्प जोड़ा है। उस विकल्प के साथ, struct in6_pktinfo सहायक डेटा के रूप में वापस कर दिया जाएगा।

+0

धन्यवाद, यही वह है जिसे मैं ढूंढ रहा था। बहुत बुरा यह पाइथन सॉकेट के मॉड्यूल द्वारा अभी तक समर्थित नहीं है - हालांकि मैंने इस प्रश्न में libc निर्दिष्ट किया था। :) – Readonly

0

यह थोड़ी देर के बाद से मैं सी/सी ++ टीसीपी/आईपी कोडिंग कर रहा हूं लेकिन जहां तक ​​मुझे हर संदेश (या व्युत्पन्न सॉकेट) पर याद है, तो आप आईपी शीर्षलेख की जानकारी में जा सकते हैं। इन शीर्षकों में प्राप्तकर्ता पता शामिल होना चाहिए जो आप जिस इंटरफ़ेस के बारे में पूछ रहे हैं उसका आईपी होगा।

-1
एक अलग सॉकेट के रूप में Glomek का सुझाव दिया, एक ही रास्ता है कि मैं इस निश्चित करने के लिए विंडोज एक रॉ सॉकेट, जैसे उपयोग करने के लिए है पर पता प्रत्येक इंटरफेस पर खोलने की

बाहर,

SOCKET s = socket(AF_INET, SOCK_RAW, IPPROTO_IP); 

प्रत्येक इस सॉकेट से प्राप्त होगा IP packet बनें, जिसमें स्रोत और गंतव्य दोनों पते शामिल हैं। जिस कार्यक्रम पर मैं काम करता हूं, मुझे एसआईओ_आरसीवीएल विकल्प का उपयोग करके सॉकेट को विशिष्ट मोड में रखना होगा। ऐसा करने का मतलब है कि मुझे नेटवर्क पर इंटरफ़ेस "देखता" प्रत्येक आईपी पैकेट मिलता है। मेरे आवेदन के लिए स्पष्ट रूप से पैकेट निकालने के लिए मुझे आईपी और टीसीपी/यूडीपी हेडर में पते और बंदरगाहों का उपयोग करके डेटा फ़िल्टर करना होगा। जाहिर है, यह आपकी दिलचस्पी रखने की तुलना में शायद अधिक ओवरहेड है। मैं इसे केवल यह कहने के लिए जिक्र करता हूं - मैंने कच्चे सॉकेट का उपयोग कभी भी विचित्र मोड में डाले बिना नहीं किया है। इसलिए मुझे यकीन नहीं है कि क्या आप इसे INADDR_ANY से जोड़ सकते हैं और उस बिंदु से नियमित सॉकेट के रूप में इसका उपयोग कर सकते हैं या नहीं। ऐसा लगता है कि आप कर सकते हैं; मैंने अभी कोशिश नहीं की है।

संपादित करें: विंडोज पर कच्चे सॉकेट के संबंध में सीमाओं के लिए article पढ़ें। मेरी परियोजना पर मुझे सबसे बड़ी बाधा आई थी कि विंडोज 2000 और बाद में कच्चे सॉकेट खोलने के लिए प्रशासक समूह का सदस्य होना चाहिए।

7

dwc सही है, आईपीवी 6_PKTINFO लिनक्स पर आईपीवी 6 के लिए काम करेगा।

इसके अलावा, IP_PKTINFO आईपीवी 4 के लिए काम करेंगे - आप मैनपेज आईपी (7)

+1

लिनक्स पूरी दुनिया नहीं है। पोर्टेबिलिटी मुद्दों के बारे में जागरूक होना अच्छा है। – dwc

+2

@dwc: यदि आपके पास लिनक्स नहीं है तो आपको इसे अनुकरण करना चाहिए: पी –

2

में विवरण देख सकते हैं मैं एक उदाहरण है कि स्रोत, गंतव्य और इंटरफ़ेस पतों के अर्क का निर्माण किया गया है। संक्षिप्तता के लिए, कोई त्रुटि जांच प्रदान नहीं की जाती है। यह डुप्लिकेट देखें: Get destination address of a received UDP packet

// sock is bound AF_INET socket, usually SOCK_DGRAM 
// include struct in_pktinfo in the message "ancilliary" control data 
setsockopt(sock, IPPROTO_IP, IP_PKTINFO, &opt, sizeof(opt)); 
// the control data is dumped here 
char cmbuf[0x100]; 
// the remote/source sockaddr is put here 
struct sockaddr_in peeraddr; 
// if you want access to the data you need to init the msg_iovec fields 
struct msghdr mh = { 
    .msg_name = &peeraddr, 
    .msg_namelen = sizeof(peeraddr), 
    .msg_control = cmbuf, 
    .msg_controllen = sizeof(cmbuf), 
}; 
recvmsg(sock, &mh, 0); 
for (// iterate through all the control headers 
    struct cmsghdr *cmsg = CMSG_FIRSTHDR(&mh); 
    cmsg != NULL; 
    cmsg = CMSG_NXTHDR(&mh, cmsg)) 
{ 
    // ignore the control headers that don't match what we want 
    if (cmsg->cmsg_level != IPPROTO_IP || 
     cmsg->cmsg_type != IP_PKTINFO) 
    { 
     continue; 
    } 
    struct in_pktinfo *pi = CMSG_DATA(cmsg); 
    // at this point, peeraddr is the source sockaddr 
    // pi->ipi_spec_dst is the destination in_addr 
    // pi->ipi_addr is the receiving interface in_addr 
} 
संबंधित मुद्दे