📘
Beej's Guide to Network Programming 正體中文版
  • 簡介
  • 原著資訊
  • 譯者誌謝
  • 進階資料
  • 簡體中文版
  • 中文授權
  • 聯絡譯者
  • 1. 導讀
    • 1.1. 本書的讀者
    • 1.2. 平台與編譯器
    • 1.3. 官方網頁與書本
    • 1.4. Solaris/SunOS 程式設計師該注意的事
    • 1.5. Windows 程式設計師該注意的事
    • 1.6. 來信原則
    • 1.7. 鏡射站台(Mirroring)
    • 1.8. 譯者該注意的
    • 1.9. 版權與散佈
  • 2. 何謂 Socket
    • 2.1 兩種 Internet Sockets
    • 2.2 底層漫談與網路理論
  • 3. IP address、結構與資料轉換
    • 3.1. IPv4 與 IPv6
      • 3.1.1. Sub network (子網段)
      • 3.1.2. Port Number(連接埠號碼)
    • 3.2. Byte Order(位元組順序)
    • 3.3. 資料結構
    • 3.4. IP 位址,續集
      • 3.4.1 Private Network
  • 4. 從 IPv4 移植為 IPv6
  • 5. System call 或 Bust
    • 5.1. getaddrinfo()-準備開始!
    • 5.2. socket()-取得 File Descriptor!
    • 5.3. bind()- 我在哪個 port?
    • 5.4. connect(),嘿!你好。
    • 5.5. listen()-有人會呼叫我嗎?
    • 5.6. accept()- 謝謝你 call 3490 port
    • 5.7. send() 與 recv()- 寶貝,我們來聊天!
    • 5.8. sendto() 與 recvfrom()- 來點 DGRAM
    • 5.9. close() 與 shutdown()- 你消失吧!
    • 5.10. getpeername()-你是誰?
    • 5.11. gethostname()-我是誰?
  • 6. Client-Server 基礎
    • 6.1. 簡單的 Stream Server
    • 6.2. 簡單的 Stream Client
    • 6.3. Datagram Sockets
  • 7. 進階技術
    • 7.1. Blocking(阻塞)
    • 7.2. select():同步 I/O 多工
    • 7.3. 不完整傳送的後續處理
    • 7.4. Serialization:如何封裝資料
    • 7.5. 資料封裝
    • 7.6. 廣播封包:Hello World!
  • 8. 常見的問題
  • 9. Man 使用手冊
    • 9.1. accept()
    • 9.2. bind()
    • 9.3. connect()
    • 9.4. close()
    • 9.5. getaddrinfo(), freeaddrinfo(), gai_strerror()
    • 9.6. gethostname()
    • 9.7. gethostbyname(), gethostbyaddr()
    • 9.8. getnameinfo()
    • 9.9. getpeername()
    • 9.10. errno
    • 9.11. fcntl()
    • 9.12. htons(), htonl(), ntohs(), ntohl()
    • 9.13. inet_ntoa(), inet_aton(), inet_addr
    • 9.14. inet_ntop(), inet_pton()
    • 9.15. listen()
    • 9.16. perror(), strerror()
    • 9.17. poll()
    • 9.18. recv(), recvfrom()
    • 9.19. select()
    • 9.20. setsockopt(), getsockopt()
    • 9.21. send(), sendto()
    • 9.22. shutdown()
    • 9.23. socket()
    • 9.24. struct sockaddr and pals
  • 10. 參考資料
    • 10.1. 書籍
    • 10.2. 網站參考資料
    • 10.3. RFC
  • 11. 原著誌謝
Powered by GitBook
On this page
  • 函式原型
  • 說明
  • 傳回值
  • 範例
Edit on GitHub
  1. 9. Man 使用手冊

9.12. htons(), htonl(), ntohs(), ntohl()

將多位元組整數型別(multi-byte integer types)由 host byte order 轉換為 network byte order

函式原型

#include <netinet/in.h>

uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);

說明

這真的只是來亂的,不同的電腦在多位元組整數[比如:任何比字元長的整數]都用不同的 byte orderings(位元組順序)。結果變成,如果你從 Intel 主機用 send() 送出一個兩 bytes 的 short int 給 Mac 主機[我是指在它們都成為 Intel 架構以前的事了],在一台電腦上認為是 1 的數值,到了另一台電腦上卻可能是 256,反之亦然。

避免這個問題的方法是請大家拋開這些差異,並同意 Motorola 與 IBM 才是正道,而 Intel 的方法是旁門左道。所以我們應該在送出資料以前,先將我們的 byte ordering 轉換為 "big-endian",因為 Intel 是 "little-endian" 的電腦。我們將偏好的 byte order 稱為 "Network Byte Order" 是很正確的,所以這些函式會將你電腦的 byte order 轉換為 network byte order,然後對方再轉回來。

(這表示在 Intel 電腦上,這些函式旋轉了全部的 bytes 順序,而在 PowerPC 上,它們什麼都不用做,因為 PowerPC 就是以 Network Byte Order 的方式儲存資料。但無論如何你的程式碼應該每次都要用這些函式,因為有人可能會想在 Intel 電腦上執行你的程式,而你的程式還是得正常運作。)

注意,相關的型別是 32-bit(4 byte,可能是 int)與 16-bit(2 byte,很有可能是 short)的數值。64-bit 的電腦可能有一個 htonll() 來轉換 64-bit 的整數,但是我還沒看過,你可以自己寫一個。

不管怎樣,這些函式運作的方式就是,你要先決定是從(你電腦的)host byte order 轉換,還是從 network byte order 轉換。如果是從 "host",那你要呼叫的函式開頭就是 "h",否則就是 network 的 "n"。中間的函式名稱永遠都是 "to",因為你是從某一種順序轉換到("to")另一種,而倒數第二個字母表示你要轉換的目的格式。最後的字母就是資料的大小,"s" 表示 short、"l" 表示 long,如下所示:

htons()   host to network short
htonl()   host to network long
ntohs()   network to host short
ntohl()   network to host long

傳回值

每個函式傳回轉換過的值

範例

uint32_t some_long = 10;
uint16_t some_short = 20;

uint32_t network_byte_order;

// 轉換與傳送
network_byte_order = htonl(some_long);
send(s, &network_byte_order, sizeof(uint32_t), 0);

some_short == ntohs(htons(some_short)); // 這行判斷式為真
Previous9.11. fcntl()Next9.13. inet_ntoa(), inet_aton(), inet_addr

Last updated 2 years ago