2016-04-28 5 views
6

को समझना मैं कुछ यूड पैकेट को स्थानीयहोस्ट भेजने के परीक्षण के लिए यूनिक्स सॉकेट का उपयोग करने की कोशिश कर रहा हूं।htonl() और ntohl()

यह मेरी समझ है कि पैकेट भेजने के लिए आईपी पता और बंदरगाह सेट करते समय, मैं अपने sockaddr_in को नेटवर्क-बाइट ऑर्डर में परिवर्तित मानों के साथ भर दूंगा। मैं पर OSX हूँ और मैं चकित है कि इस

printf("ntohl: %d\n", ntohl(4711)); 
printf("htonl: %d\n", htonl(4711)); 
printf("plain: %d\n", 4711); 

प्रिंटों

ntohl: 1729232896 
htonl: 1729232896 
plain: 4711 

तो न समारोह वास्तव में सादे मान देता हूँ। मुझे उम्मीद है कि परिणाम अलग-अलग होंगे, क्योंकि x86 छोटा-अंत (afaik) है, या समान और वास्तविक संख्या 4711 जैसा ही है। स्पष्ट रूप से मुझे समझ में नहीं आता कि htonl और ntohl और उनके रूप क्या हैं। मैं क्या खो रहा हूँ?

int main(int argc, char *argv[]) 
{ 
    if (argc != 4) 
    { 
     fprintf(stderr, "%s\n", HELP); 
     exit(-1); 
    } 

    in_addr_t rec_addr = inet_addr(argv[1]); // first arg is '127.0.0.1' 
    in_port_t rec_port = atoi(argv[2]);  // second arg is port number 
    printf("Address is %s\nPort is %d\n", argv[1], rec_port); 
    char* inpath = argv[3]; 

    char* file_buf; 
    unsigned long file_size = readFile(inpath, &file_buf); // I am trying to send a file 
    if (file_size > 0) 
    { 
     struct sockaddr_in dest; 
     dest.sin_family  = AF_INET; 
     dest.sin_addr.s_addr = rec_addr; // here I would use htons 
     dest.sin_port  = rec_port; 
     printf("ntohs: %d\n", ntohl(4711)); 
     printf("htons: %d\n", htonl(4711)); 
     printf("plain: %d\n", 4711); 
     int socket_fd = socket(AF_INET, SOCK_DGRAM, 0); 
     if (socket_fd != -1) 
     { 
     int error; 
     error = sendto(socket_fd, file_buf, file_size + 1, 0, (struct sockaddr*)&dest, sizeof(dest)); 
     if (error == -1) 
      fprintf(stderr, "%s\n", strerror(errno)); 
     else printf("Sent %d bytes.\n", error); 
     } 
    } 

    free(file_buf); 
    return 0; 
} 
+0

ध्यान दें कि आपका टेक्स्ट "htons" और "ntohs" कहता है, लेकिन आप वास्तव में 'htonl() 'और' ntohl() 'को कॉल कर रहे हैं। –

+0

@ जॉन बोलिंगर हां, जो एक ही परिणाम के साथ दोनों की कोशिश करने से आया, टिप्पणी के लिए धन्यवाद। – oarfish

उत्तर

3

दोनों कार्यों बाइट्स 'क्रम को उल्टा:

प्रासंगिक कोड यह है। वह खुद तर्क क्यों लौटाएगा?

htons(ntohs(4711)) और ntohs(htons(4711)) आज़माएं।

+0

उम ... ठीक है। मुझे लगता है कि वास्तविक सवाल यह है कि मैं स्थानीयहोस्ट को कुछ भी भेजने में असमर्थ क्यों हूं जब तक कि मैं सादे आईपी पते का उपयोग नहीं करता, लेकिन यह एक अलग मुद्दा है। – oarfish

3

"नेटवर्क बाइट ऑर्डर" हमेशा बड़े एंडियन का मतलब है।

"होस्ट बाइट ऑर्डर" मेजबान की वास्तुकला पर निर्भर करता है। सीपीयू के आधार पर, होस्ट बाइट ऑर्डर थोड़ा एंडियन, बड़ा एंडियन या कुछ और हो सकता है। (जी) libc आर्किटेक्चर होस्ट करने के लिए अनुकूल है।

क्योंकि इंटेल आर्किटेक्चर थोड़ा एंडियन है, इसका मतलब है कि दोनों कार्य समान हैं: बाइट ऑर्डर को उलटाना।

+1

"नेटवर्क बाइट ऑर्डर" _big endian_ का अर्थ विकसित हुआ। यह वैसे भी नहीं था। यह असाधारण रूप से आम है। https://en.wikipedia.org/wiki/Endianness#Networking – chux

5

जैसा कि अन्य ने उल्लेख किया है, htons और ntohs दोनों छोटी-छोटी मशीन पर बाइट ऑर्डर को उलट देते हैं, और बड़े-एंडियन मशीनों पर नो-ऑप्स नहीं हैं।

क्या उल्लेख नहीं किया गया था कि ये कार्य 16-बिट मान लेते हैं और 16-बिट मान वापस करते हैं। यदि आप 32-बिट मानों को कनवर्ट करना चाहते हैं, तो आप इसके बजाय htonl और ntohl का उपयोग करना चाहते हैं।

इन कार्यों के नाम कुछ डेटाटाइप के पारंपरिक आकार से आते हैं। sshort के लिए खड़ा है जबकि llong के लिए खड़ा है। short आमतौर पर 16-बिट है जबकि पुराने सिस्टम long 32-बिट था।

अपने कोड में, आप rec_addr पर htonl कॉल करने के लिए, क्योंकि वह मूल्य inet_addr द्वारा दिया गया था, और है कि समारोह नेटवर्क बाइट क्रम में पता देता है की जरूरत नहीं है।

आपको rec_port पर htons पर कॉल करने की आवश्यकता है।

+0

यदि मैं लोकलहोस्ट पर चल रहे दो प्रोग्रामों के बीच पैकेट भेजने की कोशिश करता हूं, और 'htons' के साथ' rec_port' का इलाज करता हूं, 8080 368 9 5 में बदल जाता है। – oarfish

2

इन कार्यों का खराब नाम है।Host to network और network to host वास्तव में एक ही बात है और वास्तव में बुलाया जाना चाहिए रहे हैं

एक छोटे endian मशीन पर

तो 'परिवर्तन endianness अगर यह एक छोटे endian मशीन है' आप

net, ie be, number = htonl/ntohl (le number) 

करते हैं और पर नंबर होना भेज तार। और जब आप एक बड़ा अंत मशीन पर तार

le num = htonl/ntohl (net ,ie be, number) 

से एक बड़ा endian नंबर मिल

net, ie be, number = htonl/ntohl (be number) 

और

be num = htonl/ntohl (net ,ie be, number) 

और पिछले मामलों आप देखते हैं कि इन कार्यों में कुछ भी नहीं

+0

ठीक है, सावधान रहें। यद्यपि कुछ हैं, यदि कोई हैं, तो इन दिनों मशीनें जो बाइट ऑर्डर का उपयोग छोटे-एंडियन और बड़े-एंडियन दोनों से अलग होती हैं, कुछ प्रमुखता के साथ अतीत में ऐसी मशीनें होती हैं। यह कम से कम कल्पनाशील है कि वर्तमान या भविष्य की मशीनें कहां कहती हैं, 'htonl() 'अपने स्वयं के विपरीत नहीं है। पॉज़िक्स ने इन कार्यों को संभालने में सक्षम होने के लिए इंजीनियर किया ताकि उन्हें कभी भी करने की आवश्यकता हो। –

+0

ठीक है तो इसे 'बड़े अंत में मशीन बदलना' कहा जाना चाहिए यदि यह एक बड़ी एंडियन मशीन नहीं है ' – pm100

+1

भले ही दोनों कार्य एक ही काम करते हैं, उनके लिए अलग-अलग नाम होने के बावजूद भी उपयोगी है क्योंकि यह कोड के इरादे को स्पष्ट करता है - यानी अगर मैं x = ntohl (blah) देखता हूं, मुझे पता है कि एक्स को आवंटित मान अर्थपूर्ण रूप से सार्थक होगा, जबकि यदि मैं x = htonl (blah) देखता हूं, तो मुझे पता है कि x का मान वह नहीं है जिसे मैं मूल- endian। अगर कोड सिर्फ x = may_endian_swap (blah) था, तो यह मेरे लिए स्पष्ट नहीं होगा कि मैं उदा। printf ("% i \ n", x); बाद में और एक अर्थात् अर्थपूर्ण मूल्य मुद्रित देखें। –

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