嵌入式Linux網路程式設計,網路基礎,套接字socket(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW),IP地址,埠號,位元組序,位元組序轉換函式,IP地址的轉換
文章目錄
1,socket
- socket是一個應用程式設計的介面
- socket代表著網路程式設計的一種資源,是一種特殊的檔案描述符 (everything in Unix is a file):對它執行IO的操作函式,比如,read(),write(),close()等操作函式
- 並不僅限於TCP/IP協議
- 面向連線 (Transmission Control Protocol - TCP/IP)
- 無連線 (User Datagram Protocol -UDP 和 Inter-network Packet Exchange - IPX)
1.1,socket的型別(SOCK_STREAM、SOCK_DGRAM、SOCK_RAW)
- 流式套接字(SOCK_STREAM): 唯一對應著TCP
提供了一個面向連線、可靠的資料傳輸服務,資料無差錯、無重複的傳送且按傳送順序接收。內設定流量控制,避免資料流淹沒慢的接收方。資料被看作是位元組流,無長度限制。 - 資料報套接字(SOCK_DGRAM): 唯一對應著UDP
提供無連線服務。資料包以獨立資料包的形式被髮送,不提供無差錯保證,資料可能丟失或重複,順序傳送,可能亂序接收。 - 原始套接字(SOCK_RAW):(對應著多個協議,傳送穿透了傳輸層)
可以對較低層次協議如IP、ICMP直接訪問。
1.2,socket的位置
2,IP地址
- IP地址是Internet中主機的標識
·Internet中的主機要與別的機器通訊必須具有一個IP地址
·IP地址為32位(IPv4)或者128位(IPv6)
·mobileIPV6: local IP(本地註冊的IP),roam IP(漫遊IP)
·每個資料包都必須攜帶目的IP地址和源IP地址,路由器依靠此資訊為資料包選擇路由 - 表示形式:常用點分形式,如202.38.64.10,最後都會轉換為一個32位的無符號整數。
- IP地址分類
- 子網掩碼(跟區域網相關)
2.1,特殊IP地址:
-
區域網IP:
·192.XXX.XXX.XXX
·10.XXX.XXX.XXX -
廣播IP:
·xx.xxx.xxx.255,
·255.255.255.255(全網廣播,大部分企業都會限制) -
組播IP: (不能以255結尾,以224~239開頭)
·224.XXX.XXX.XXX~239.xxx.xxx.xxx
3,埠號
-
為了區分一臺主機接收到的資料包應該轉交給哪個程序(哪個任務)來進行處理,使用埠號來區別
-
TCP埠號與UDP埠號獨立
-
埠號是一個16位的數字(1-65535)
-
埠號一般由IANA (Internet Assigned Numbers Authority) 管理
·眾所周知埠:1 ∼ 1023(1 ∼ 255之間為眾所周知埠,256~1023埠通常由UNIX系統佔用。FTP: 21,SSH: 22, HTTP:80, HTTPS:469)
·註冊埠(保留埠):1024~49150
·動態或私有埠:49151~65535
保留埠: 1024-5000(不建議使用)
可以使用的:5000~65535 -
網路裡面的通訊是由 IP地址+埠號 來決定
4,位元組序(大端序、小端序)
- 位元組序是指不同的CPU訪問記憶體中的多位元組資料時候,存在大小端(位元組序)問題,如CPU訪問的是字串,則不存在大小端問題
- 不同型別CPU的主機中,記憶體儲存多位元組整數序列有兩種方法,稱為主機位元組序(HBO):
·小端序(little-endian) - 低序位元組儲存在低地址
將低位元組儲存在起始地址,稱為“Little-Endian”位元組序,Intel、AMD等採用的是這種方式(X86/ARM);
·大端序(big-endian)- 高序位元組儲存在低地址
將高位元組儲存在起始地址,稱為“Big-Endian”位元組序,由ARM、Motorola等所採用(powerpc/mips, ARM作為路由器時) - 網路中傳輸的資料必須按網路位元組序,即大端位元組序
- 在大部分PC機上,當應用程序將整數送入socket前,需要轉化成網路位元組序;當應用程序從socket取出整數後,要轉化成小端位元組序(原因?)
4.1,位元組序(網路位元組序(NBO和主機位元組序HBO)
- 網路位元組序(NBO - Network Byte Order)
·使用統一的位元組順序,避免相容性問題 - 主機位元組序(HBO - Host Byte Order)
·不同的機器HBO是不一樣的,這與CPU的設計有關
·Motorola 68K系列、ARM系列,HBO與NBO是一致的
·Intel X86系列,HBO與NBO不一致 - Intel CPU採用小端序做主機序,網路中傳輸的資料必須按網路位元組序,即大端位元組序.因此,在大部分PC機上,當應用程序將整數送入socket前,需要轉化成網路序;當應用程序從socket取出整數後,要轉化成主機序
- 把給定系統所採用的位元組序稱為主機位元組序。為了避免不同類別主機之間在資料交換時由於對於位元組序的不同而導致的差錯,引入了網路位元組序。
4.2,位元組序轉換函式htonl()/htons()、ntohl()/ntohs()
- 主機位元組序到網路位元組序(host to network)
·u_long htonl (u_long hostlong);
·u_short htons (u_short short); - 網路位元組序到主機位元組序(network to host)
·u_long ntohl (u_long hostlong);
·u_short ntohs (u_short short);
5,IP地址的轉換 inet_aton()、inet_addr()、inet_ntoa()、inet_pton()
inet_aton( )
#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);
- 將strptr所指的字串轉換成32位的網路位元組序二進位制值
inet_addr( )
int_addr_t inet_addr(const char *strptr);
- 功能同上,返回轉換後的地址。
- strptr是以’\0’結尾的IPv4點分形式的IP地址字串,該函式返回結果是32位的整數地址,如果字串包含的不是合法的IP地址,則函式返回-1。(內部包含了位元組序的轉換,預設是網路位元組序的模式)
- 特點:
- 僅適應於IPV4
- 當出錯時,返回-1(在計算機記憶體儲是補碼的形式255.255.255.255)
- 此函式不能用於255.255.255.255的轉換
例如:
struct in_addr addr;
addr.s_addr = inet_addr(" 192.168.1.100 ");
inet_ntoa( )
char *inet_ntoa(stuct in_addr inaddr);
- 將32位網路位元組序二進位制地址轉換成點分十進位制的字串。
- inaddr是IPv4地址結構,函式返回一指向包含點分IP地址的靜態儲存區字元指標。如果錯誤則函式返回NULL
inet_pton()
int inet_pton(int af, const char *src, void *dst);
- 將IPV4/IPV6的地址轉換成binary格式(內部包含了位元組序的轉換,預設是網路位元組序的模式)
- 能正確的處理255.255.255.255的轉換問題
- 引數:
- af: 地址協議族(AF_INET或AF_INET6)
- src:是一個指標(填寫點分形式的IP地址[主要指IPV4])
- dst: 轉換的結果給到dst
- 返回值
inet_pton() returns 1 on success (network address was successfully con‐verted). 0 is returned if src does not contain a character string representing a valid network address in the specified address family. If af does not contain a valid address family, -1 is returned and errno is set to EAFNOSUPPORT.
inet_ntop()
#include <arpa/inet.h>
const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);
- 將IPV4/IPV6的網路位元組序地址,變成本地的字串形式的IP地址
- 能正確的處理(-1)255.255.255.255的轉換問題
- 引數:
- af: 地址協議族(AF_INET或AF_INET6)
- src:是一個指標(32位的網路位元組序IP地址)
- dst: 轉換的結果為點分形式的IP地址[主要指IPV4]
- size:src的長度
- 返回值
·On success, inet_ntop() returns a non-NULL pointer to dst.
·NULL is returned if there was an error, with errno set to indicate the error.