一、什麼是socket
socket可以看成是使用者程序與核心網絡協定棧的程式設計接口。
socket不僅可以用于本機的程序間通信,還可以用于網絡上不同主機的程序間通信。

socket API是一層抽象的網絡程式設計接口,适用于各種底層網絡協定,如IPv4、IPv6,以及以後要講的UNIX Domain Socket。然而,各種網絡協定的位址格式并不相同,如下圖所示:
IPv4和IPv6的位址格式定義在netinet/in.h中,IPv4位址用sockaddr_in結構體表示,包括16位端口号和32位IP位址,如下所示:
sa_family_t是一個無符号短整型(unsigned short)。in_addr_t資料類型必須是一個至少32位的無符号整數類型,in_port_t必須是一個至少16位的無符号的整數類型。
IPv6位址用sockaddr_in6結構體表示,包括16位端口号、128位IP位址和一些控制字段。UNIX Domain Socket的位址格式定義在sys/un.h中,用sockaddr_un結構體表示。各種socket位址結構體的開頭都是相同的,前16位表示整個結構體的長度(并不是所有UNIX的實作都有長度字段,如Linux就沒有),後16位表示位址類型。IPv4、IPv6和UNIX Domain Socket的位址類型分别定義為常數AF_INET、AF_INET6、AF_UNIX。這樣,隻要取得某種sockaddr結構體的首位址,不需要知道具體是哪種類型的sockaddr結構體,就可以根據位址類型字段确定結構體中的内容。是以,socket API可以接受各種類型的sockaddr結構體指針做參數,例如bind、accept、connect等函數,這些函數的參數應該設計成void *類型以便接受各種類型的指針,但是sock API的實作早于ANSI C标準化,那時還沒有void *類型,是以這些函數的參數都用struct sockaddr *類型表示,即通用位址結構,如下所示:
sin_family:指定該位址家族
sa_data:由sin_family決定它的形式。
在傳遞參數之前要強制類型轉換一下,例如:
struct sockaddr_in servaddr;
/* initialize servaddr *
/bind(listen_fd, (struct sockaddr *)&servaddr, sizeof(servaddr));
二、網絡位元組序
位元組序
大端位元組序(Big Endian)
最高有效位(MSB:Most Significant Bit)存儲于最低記憶體位址處,最低有效位(LSB:Lowest Significant Bit)存儲于最高記憶體位址處。
小端位元組序(Little Endian)
最高有效位(MSB:Most Significant Bit)存儲于最高記憶體位址處,最低有效位(LSB:Lowest Significant Bit)存儲于最低記憶體位址處。
主機位元組序
不同的主機有不同的位元組序,如x86為小端位元組序,Motorola 6800為大端位元組序,ARM位元組序是可配置的。
網絡位元組序
網絡位元組序規定為大端位元組序
為使網絡程式具有可移植性,使同樣的C代碼在大端和小端計算機上編譯後都能正常運作,可以調用以下庫函數做網絡位元組序和主機位元組序的轉換。
這些函數名很好記,h表示host,n表示network,l表示32位長整數,s表示16位短整數。例如htonl表示将32位的長整數從主機位元組序轉換為網絡位元組序,例如将IP位址轉換後準備發送。如果主機是小端位元組序,這些函數将參數做相應的大小端轉換然後傳回,如果主機是大端位元組序,這些函數不做轉換,将參數原封不動地傳回。
下面寫個小程式測試下主機的大小端:
運作結果:
即本主機是小端位元組序,而經過htonl 轉換後為網絡位元組序,即大端。
三、位址轉換函數
前面提到的 sockaddr_in 結構體中的成員struct in_addr sin_addr表示32位的IP位址。但是我們通常用點分十進制的字元串表示IP位址,以下函數可以在字元串表示和in_addr表示之間轉換。
字元串轉in_addr的函數:
注意:轉換而成的32位數是網絡位元組序的。
in_addr轉字元串的函數:
注意:傳入的32位數也是網絡位元組序的。
其中inet_pton和inet_ntop不僅可以轉換IPv4的in_addr,還可以轉換IPv6的in6_addr,是以函數接口是void *addrptr。
下面寫個小程式示範一下:
注意,在列印addr的時候先轉換成主機位元組序,否則輸出可能是負數。
四、套接字類型
流式套接字(SOCK_STREAM)
提供面向連接配接的、可靠的資料傳輸服務,資料無差錯,無重複的發送,且按發送順序接收。
資料報式套接字(SOCK_DGRAM)
提供無連接配接服務。不提供無錯保證,資料可能丢失或重複,并且接收順序混亂。
原始套接字(SOCK_RAW)