1. 程式人生 > 實用技巧 >AF_INET與套接字SOCKET

AF_INET與套接字SOCKET

一、SOCKET——套接字

套接字最初是為同一主機上的應用程式所建立,使得主機上執行的一個程式(又名一個程序)與另一個執行的程式進行通訊。這就是所謂的程序間通訊(Inter Process Communication,IPC)

有兩種型別的套接字:基於檔案的和面向網路的。

(1)基於檔案的
家族名:AF_UNIX

又名AF_LOCAL,在POSIX1.g標準中指定,它代表地址家族(addressfamily):UNIX。其他比較舊的系統可能會將地址家族表示成域(domain)或協議家族(protocolfamily),並使用其縮寫PF而非AF。類似地,AF_LOCAL(在2000~2001年標準化)將代替AF_UNIX。

(2)面向網路的

家族名:AF_INET

或者地址家族:因特網。另一個地址家族AF_INET6用於第6版因特網協議(IPv6)定址。此外,還有其他的地址家族,這些要麼是專業的、過時的、很少使用的,要麼是仍未實現的。在所有的地址家族之中,目前AF_INET是使用得最廣泛的。

二、套接字地址:主機-埠對

做個比喻,套接字就像一個電話插孔,主機名和埠號就像區號和號碼。
當程式之間需要通訊時,需要知道對端的主機名(IP)和埠號。
有效的埠號範圍為0~65535(小於1024的埠號預留給了系統)

什麼是Socket?

再舉一個例子:

Lewis跟Nico兩人聊QQ,QQ是一個獨立的應用程式,那麼它對應了兩個Socket,一個在Lewis的電腦上,一個在Nico的電腦上。當Lewis對Nico說:”週末我們去開卡丁車吧!“,這句話就是一段資料,這段資料會先儲存在Lewis電腦Socket上,我們在”分層網路模型“一文中提到過,TCP存在於傳輸層,同時,我們在”埠、IP協議“一文中又提到了TCP傳輸過程(三次握手建立連線,三次握手關閉連線),當Lewis的QQ和Nico的QQ連線成功後,Lewis的Socket將這段話的資料傳送到Nico的電腦中,但是Nico暫時還沒看到,因為資料會先存放在Nico電腦的Socket當中,然後Socket會把資料呈現給Nico看。

到了這裡不禁要問,資料傳送過程中為什麼要多出Socket這樣東西?
答:因為不同的應用程式對應不同的Socket,而Socket保證了QQ的資料不會到處亂跑,不會一衝動跑到MSN上去了。因為QQ和MSN兩個應用程式的Socket內容是完全不同的。那麼Socket裡面到底是什麼?
答:Socket套接字地址!套接字地址是一個數據結構,我們僅基於TCP傳輸協議作為例子。套接字地址這個資料結構裡面包含了:地址型別、埠號、IP地址、填充位元組這4種資料。而它的資料結構原型為:

 #include <netinet/in.h>
    struct sockaddr_in{
     unsigned short         sin_family;    
     unsigned short int     sin_port;      
     struct in_addr         sin_addr;      
     unsigned char          sin_zero[8];   
  };

其中:

    • sin_family表示地址型別,對於基於TCP/IP傳輸協議的通訊,該值只能是AF_INET;
    • sin_prot表示埠號,例如:21 或者 80 或者 27015,總之在0 ~ 65535之間;
    • sin_addr表示32位的IP地址,例如:192.168.1.5 或 202.96.134.133;
    • sin_zero表示填充位元組,一般情況下該值為0;
      Socket資料的賦值例項:
struct sockaddr_in Lewis;
  Lewis.sin_family      = AF_INET;
  Lewis.sin_port        = htons(80);
  Lewis.sin_addr.s_addr = inet_addr("202.96.134.133");
  memset(Lewis.sin_zero,0,sizeof(Lewis.sin_zero));

分析:我們設定了一個名叫Lewis的套接字地址,它基於TCP/IP協議,因此sin_family的值為AF_INET,這個是雷打不動的,只要使用TCP/IP協議簇,該值就是AF_INET;htons是埠函式,以後介紹,這就表示設定了埠號為80;
sin_addr是一個數據結構,原型是:

  struct in_addr{
     unsigned long     s_addr;
};

三、面向連線的套接字與無連線的套接字

1、面向連線的套接字
TCP套接字的名字SOCK_STREAM。
特點:可靠,開銷大。

在進行通訊之前必須先建立一個連線,該連線的通訊提供序列化的、可靠的和不重複的資料交付,而沒有記錄邊界。這種型別的通訊也稱為虛擬電路或流套接字。
實現這種連線型別的主要協議是傳輸控制協議(縮寫 TCP)
為了建立 TCP套接字,必須使用 SOCK_STREAM 作為套接字型別。

2、無連線的套接字
UDP套接字的名字SOCK_DGRAM
特點:不可靠(局網內還是比較可靠的),開銷小。

與虛擬電路形成鮮明對比的是資料報型別的套接字,它是一種無連線的套接字。
在通訊開始之前並不需要建立連線。此時,在資料傳輸過程中並無法保證它的順序性、可靠性或重複性。資料報確實儲存了記錄邊界,這就意味著訊息是以整體傳送的,而並非首先分成多個片段。
實現這種連線型別的主要協議是使用者資料報協議(縮寫 UDP)。為了建立UDP套接字,必須使用SOCK_DGRAM作為套接字型別。
UDP套接字的SOCK_DGRAM名字來自於單詞“datagram”(資料報)

參考:

1.簡單理解socket(AF_INET&SOCK_STREAM,SOCK_DGRAM)

2.AF_INET與套接字