सबसे पहले जब आप मूल्यों साथ काम कर रहे हैं, तो आप, struct sockaddr_storage
उपयोग करने की आवश्यकता के बाद से struct sockaddr
संकेत के लिए ही सुरक्षित है, या आप आकार और संरेखण समस्याओं में चलेंगे।
दूसरा, struct sockaddr
"बेस क्लास" के लिए सी में क्या गुजरता है। पहला सदस्य sa_family_t sa_family;
है (हालांकि, चूंकि यह struct
अलग-अलग नामस्थानों में होने वाले संरचना सदस्यों को पूर्व निर्धारित करता है, प्रत्येक "सबक्लास" एक अद्वितीय उपसर्ग का उपयोग करता है (मैं कम से कम 40 उप-वर्गों में आ गया हूं))।
तीसरा - जबकि आप प्रत्येक struct
सोच सकते हैं, यह पता चला है कि कक्षा का आकार कर्नेल/लाइब्रेरी संस्करणों के बीच भिन्न होता है। तो, आप हमेशा को sizeof()
वास्तविक struct sockaddr_FOO
पास करने के लिए पास करना होगा। उदाहरण के लिए, struct sockaddr_in6
के पुराने संस्करणों में sin6_scope_id
सदस्य नहीं थे।
आप शायद विवेक के लिए एक struct
में इस लपेट करना चाहिए (और विभिन्न सहायक कार्यों प्रदान करते हैं):
struct SocketAddress
{
struct sockaddr_storage addr;
socklen_t addr_len;
};
फिर, अपनी तुलना कोड दिखाई देगा:
// returns < 0 if (left < right)
// returns > 0 if (left > right)
// returns 0 if (left == right)
// Note that in general, "less" and "greater" are not particularly
// meaningful, but this does provide a strict weak ordering since
// you probably need one.
int socket_cmp(struct SocketAddress *left, struct SocketAddress *right)
{
socklen_t min_addr_len = MIN(left->addr_len, right->addr_len;
// If head matches, longer is greater.
int default_rv = right->addr_len - left->addr_len;
int rv = memcmp(left, right, min_addr_len);
return rv ?: default_rv;
}
लेकिन रुकिए! जबकि उपरोक्त कोड पर्याप्त है, यदि आप सावधान रहें, तो सावधान रहना अभी भी बहुत सारे विवरणों में शामिल है। उदाहरण के लिए:
सभी सॉकेट अपने कार्यक्रम के एक भी रन के भीतर उत्पन्न करने के लिए जा पते दिए गए हैं, या उनमें से कुछ कुछ बाहरी माध्यम से पढ़ा जाएगा? बाद के मामले के लिए, आप sin6_scope_id
जैसे मामलों को कैनोनिकल बनाना चाहते हैं।
क्या आपको उसी प्रोग्राम में आईपीवी 4 और आईपीवी 4-ऑन-आईपीवी 6 पते (मैप किए गए ffff::1.2.3.4
) से निपटना होगा? सबसे आसान तरीका है अपने कार्यक्रम में विशेष रूप से आईपीवी 6 के साथ सौदा करना, क्योंकि प्रासंगिक कार्य आईपीवी 4 पते भी स्वीकार करते हैं। सर्वोत्तम पोर्टेबिलिटी के लिए, सुनिश्चित करें कि अक्षम करें (setsockopt
का उपयोग करके) IPV6_V6ONLY
ध्वज। वैकल्पिक रूप से, आप यह ध्वज यह सुनिश्चित करने में सहायता के लिए सक्षम कर सकते हैं कि आईपीवी 6 पते में कभी भी आईपीवी 4 पता न हो। (ध्यान दें कि localhost
का लुकअप अलग है - लेकिन यह सभी डोमेन लुकअप के लिए एक सामान्य समस्या है, जो एक से अधिक परिणाम लौटा सकता है)।
- आपको यह सुनिश्चित करने की ज़रूरत है कि सभी स्ट्रक्चर पैडिंग शून्य हो।
क्या आप जानते हैं कि मैक/आईओएस पर 'sock_addr.h' पहले से ही शामिल है या नहीं? – johk95
@ johk95 जैसा कि आप यूआरएल में देख सकते हैं, sock_addr.h और sock_addr.c का स्रोत कोड वास्तव में पोस्टफिक्स प्रोजेक्ट से हैं। – kevin
[हाँ, हम जानते हैं कि ऐप्पल यह कैसे करता है।] (Https://www.imperialviolet.org/2014/02/22/applebug.html) ^^ – Downvoter