[TOC] 1. 埠號 在同一臺主機或設備上,可能有多個進程同時在使用TCP或UDP協議,埠號的作用就是區分這些不同的進程,即每個進程使用各自不同的埠號。 對於TCP協議和UDP協議,埠號都是用unsigned short類型表示,即埠號的範圍為0 65535,這65536個埠號被分為3 ...
目錄
1. 埠號
在同一臺主機或設備上,可能有多個進程同時在使用TCP或UDP協議,埠號的作用就是區分這些不同的進程,即每個進程使用各自不同的埠號。
對於TCP協議和UDP協議,埠號都是用unsigned short類型表示,即埠號的範圍為0-65535,這65536個埠號被分為3段:
- 眾所周知埠(well-known port):範圍為0-1023,這些埠被賦予了專用功能,如FTP的21埠、Web的80埠等,應用程式不能將它們用作其他功能
- 已登記埠(registered port):範圍為1024-49151
- 臨時埠:範圍為49152-65535
well-known埠在Unix系統中稱為保留埠,使用保留埠的伺服器程式,必須以root用戶啟動運行。
2. 套接字對
TCP套接字對是定義TCP連接兩個端點的四元組,包括:本地IP地址、本地埠號、對端IP地址、對端埠號,每個端點的IP地址和埠號通常稱為一個套接字。
TCP套接字對可用於唯一標識一個網路中的TCP連接。
3. 套接字地址結構
大多數套接字API都需要一個指向套接字地址結構的指針作為函數參數,每個協議族都定義它自己的套接字地址結構,這些結構的名字均以sockaddr_開頭,並以對應每個協議族的唯一尾碼結尾。
IPv4套接字地址結構
IPv4套接字地址結構通常也稱為“網際套接字地址結構”,它以sockaddr_in
命名,定義在<netinet/in.h>
頭文件中。
#include <netinet/in.h>
struct in_addr
{
in_addr_t s_addr; //32-bit IPv4 address, network byte ordered
};
struct sockaddr_in
{
uint8_t sin_len; //length of structure
sa_family_t sin_family; //AF_INET
in_port_t sin_port; //16-bit TCP Or UDP port number, network byte ordered
struct in_addr sin_addr; //IPv4 address structure
char sin_zero[8]; //unused
};
- IPv4地址和埠號在套接字地址結構中必須以網路位元組序存儲
- IPv4地址可以按sockaddr_in.sin_addr和sockaddr_in.sin_addr.s_addr兩種方式引用
- 按照使用慣例,總是先把整個結構請0,再填寫相應欄位
- 網路通訊時,傳遞的是套接字地址結構中的某些欄位,結構本身僅在當前主機上使用
通用套接字地址結構
通用套接字地址結構struct sockaddr
定義在<sys/socket.h>
頭文件中。
#include <sys/socket.h>
struct sockaddr
{
uint8_t sa_len;
sa_family_t sa_family;
char sa_data[4];
};
對於應用程式開發人員來說,通用套接字地址結構的唯一用途就是:將特定協議的套接字地址結構指針強制類型轉換為通用套接字地址結構指針,並傳遞給套接字API。
bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
4. 位元組排序函數
- IPv4地址和埠號必須以網路位元組序存儲,TCP/IP協議中的網路位元組序採用大端位元組序
- 某個給定系統使用的位元組序叫做主機位元組序,主機位元組序可能為大端位元組序或小端位元組序
- 在填寫套接字地址結構時,必須將IPv4地址和埠號從主機位元組序轉換為網路位元組序
- 位元組排序函數用於在主機位元組序和網路位元組序之間進行轉換
#include <arpa/inet.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);
上面4個位元組排序函數只適用於整數類型,因此在套接字編程中:
- 位元組排序函數常用來轉換16位埠號和IPv4通配地址INADDR_ANY
- 其餘IP地址則一般使用地址轉換函數進行轉換
5. 地址轉換函數
地址轉換函數用於在IP地址的字元串格式和網路位元組序格式之間進行轉換。
- inet_addr()、inet_aton()、inet_ntoa()僅適用於IPv4地址轉換
- inet_pton()和inet_ntop()適用於IPv4和IPv6地址
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/*
* 字元串——>網路位元組序;
* 成功返回網路位元組序IPv4地址,失敗返回INADDR_NONE;
*/
in_addr_t inet_addr(const char *str);
/*
* 字元串——>網路位元組序,並通過addr指針保存;
* 若字元串有效則成功返回1,否則失敗返回0.
*/
int inet_aton(const char *str, struct in_addr *addr);
/*
* 網路位元組序——>字元串;
* 返回字元串格式的IPv4地址.
*/
char *inet_ntoa(struct in_addr addr);
上面三個函數有兩點需要註意:
- INADDR_NONE是一個32位都為1的整數,因此inet_addr()不能轉換地址255.255.255.255
- inet_ntoa()的參數是結構體變數,而非結構體指針