1. 程式人生 > 其它 >Linux網路程式設計-1-socket概念與地址api

Linux網路程式設計-1-socket概念與地址api

Linux網路程式設計,socket地址相關內容

socket概念

套接字(Socket),就是對網路中不同主機上的應用程序之間進行雙向通訊的端點的抽象。一個套接字就是網路上程序通訊的一端,提供了應用層程序利用網路協議交換資料的機制。從所處的地位來講,套接字上聯應用程序,下聯網路協議棧,是應用程式通過網路協議進行通訊的介面,是應用程式與網路協議根進行互動的介面 。

也可以參考wiki中的描述:

A network socket is a software structure within a network node of a computer network that serves as an endpoint for sending and receiving data across the network. The structure and properties of a socket are defined by an

application programming interface (API) for the networking architecture. Sockets are created only during the lifetime of a process of an application running in the node.

Because of the standardization of the TCP/IP protocols in the development of the Internet, the term network socket is most commonly used in the context of the

Internet protocol suite, and is therefore often also referred to as Internet socket. In this context, a socket is externally identified to other hosts by its socket address, which is the triad of transport protocol, IP address, and port number.

The term socket is also used for the software endpoint of node-internal

inter-process communication (IPC), which often uses the same API as a network socket.

socket的歷史

socket 是加州大學伯克利分校的研究人員在 20 世紀 80 年代早期提出的,所以也被叫做伯 克利套接字。伯克利的研究者們設想用 socket 的概念,遮蔽掉底層協議棧的差別。第一版 實現 socket 的就是 TCP/IP 協議,最早是在 BSD 4.2 Unix 核心上實現了 socket。很快大 家就發現這麼一個概念帶來了網路程式設計的便利,於是有更多人也接觸到了 socket 的概念。 Linux 作為 Unix 系統的一個開源實現,很早就從頭開發實現了 TCP/IP 協議,伴隨著 socket 的成功,Windows 也引入了 socket 的概念。於是在今天的世界裡,socket 成為 網路互聯互通的標準。

套接字地址格式

通用套接字地址

/* POSIX.1g 規範規定了地址族為 2 位元組的值.  */
typedef unsigned short int sa_family_t;
/* 描述通用套接字地址  */
struct sockaddr{
    sa_family_t sa_family;  /* 地址族.  16-bit*/
    char sa_data[14];   /* 具體的地址值 112-bit */
  }; 	

地址族表示使用什麼樣的方式對地址進行解釋和儲存。地址族在 glibc 裡的定義非常多,常用的有以下幾種:

  • AF_LOCAL:表示的是本地地址,對應的是 Unix 套接字,這種情況一般用於本地 socket 通訊,很多情況下也可以寫成 AF_UNIX、AF_FILE;
  • AF_INET:因特網使用的 IPv4 地址;
  • AF_INET6:因特網使用的 IPv6 地址。

其中 AF_ 是 Address Family, PF_ 的意思是 Protocol Family,是協議族的意思。一般用 AF_xxx 這樣的值來初始化 socket 地址,用 PF_xxx 這樣的值來初始化 socket。在 <sys/socket.h> 標頭檔案中可以清晰地看到,這兩個值本身就是一一對應的。

/* 各種地址族的巨集定義  */
#define AF_UNSPEC PF_UNSPEC
#define AF_LOCAL  PF_LOCAL
#define AF_UNIX   PF_UNIX
#define AF_FILE   PF_FILE
#define AF_INET   PF_INET
#define AF_AX25   PF_AX25
#define AF_IPX    PF_IPX
#define AF_APPLETALK  PF_APPLETALK
#define AF_NETROM PF_NETROM
#define AF_BRIDGE PF_BRIDGE
#define AF_ATMPVC PF_ATMPVC
#define AF_X25    PF_X25
#define AF_INET6  PF_INET6

IPV4 套接字地址

IPv4 地址族的結構如下:

/* IPV4 套接字地址,32bit 值.  */
typedef uint32_t in_addr_t;
struct in_addr
  {
    in_addr_t s_addr;
  };
  
/* 描述 IPV4 的套接字地址格式  */
struct sockaddr_in
  {
    sa_family_t sin_family; /* 16-bit */
    in_port_t sin_port;     /* 埠口  16-bit*/
    struct in_addr sin_addr;    /* Internet address. 32-bit */
 
 
    /* 這裡僅僅用作佔位符,不做實際用處  */
    unsigned char sin_zero[8];
  };

sin_family 欄位,對於 IPv4 來說就是 AF_INET。

埠號sin_port欄位,是 16-bit(2^16 = 65536),因此支援定址的埠號最多就是 65535。所謂保留埠就是大家約定俗成的,已經被對應服務廣為使用的埠,比如 ftp 的 21 埠,ssh 的 22 埠,http 的 80 埠等。一般而言,大於 5000 的埠可以作為我們自己應用程式的埠使用。

地址sin_addr欄位,為一個32-bit整數,因此最多支援2^ 32(約42億)的地址數目。

IPV6 套接字地址

ipv6地址結果如下:

struct sockaddr_in6
  {
    sa_family_t sin6_family; /* 16-bit */
    in_port_t sin6_port;  /* 傳輸埠號 # 16-bit */
    uint32_t sin6_flowinfo; /* IPv6 流控資訊 32-bit*/
    struct in6_addr sin6_addr;  /* IPv6 地址 128-bit */
    uint32_t sin6_scope_id; /* IPv6 域 ID 32-bit */
  };

地址族位 AF_INET6,埠同 IPv4 地址一樣。

地址從 32 位升級到 128 位,解決了定址數字不夠的問題。

本地套接字地址

本地套接字格式一般用來做為本地程序間的通訊, 地址族為AF_LOCAL。

struct sockaddr_un {
    unsigned short sun_family; /* 固定為 AF_LOCAL */
    char sun_path[108];   /* 路徑名 */
};

reference

[1] 百度百科

[2] wiki

[3] 極客時間·網路程式設計實戰

[4] Linux高效能伺服器程式設計