socket到底是什麼?
網路程式設計中到底如何理解socket,先看下面的圖
上面的圖表達了網路程式設計中客戶端和伺服器模型的核心邏輯。
伺服器端:首選伺服器端要先初始化號好socket,之後伺服器端執行bind函式將自己的服務能力繫結在乙個特定的位址和埠上,緊接著伺服器端呼叫listen函式將原先的socket轉化為服務端的socket,最後服務端阻塞在accept上等待客戶端的連線。
客戶端:以上服務端已經準備就緒,客戶端也需要首先初始化socket,再執行connect函式向伺服器端的位址和埠發起連線請求,這一過程就是註明的tcp三次握手過程,握手成功後雙方已經建立連線即可以進行真正的資料互動。
具體來說客戶端程序向作業系統核心發起write寫操作,核心協議棧將位元組流資料通過網路裝置傳輸到伺服器端,伺服器端從核心得到訊息,將位元組流資料從核心讀入到程序中,並開始業務邏輯的處理,完成之後服務端再將結構以同樣的方式返回給客戶端。一旦建立連線後資料傳輸的過程就不再是單向的而是雙向的,這也是tcp傳輸的乙個顯著特徵。
當客戶端和伺服器端資料互動完畢後,需要和伺服器端斷開連線時,就會執行close操作,作業系統核心此時會通知原先的連線鏈路向伺服器端傳送乙個fin包,伺服器端收到該fin包後執行被動關閉,這個時候整個鏈路處於半關閉的狀態,此後伺服器端也執行close操作,整個鏈路才真正的關閉。其中半關閉的狀態下,發起close請求的一方在沒有收到對方fin包之前都認為連線時正常的,而在全關閉狀態下,雙方都感知連線已經斷開。
以上所有的操作都是使用socket來完成的,socket是我們用來建立連線資料互動的唯一通道。
更好的理解socket,乙個直觀的結解釋
我們可以把整個tcp的網路互動和資料傳輸想象成是打**,socket就好像是我們手裡的**機,connect就好像拿起**撥打手機號,而服務端的bind就好像是拿著**號碼去電信公司註冊將**號碼和家裡的**繫結,listen就好像是聽到**響,accept就好比是拿起**開始接聽。至此三次握手建立完了,雙方可以進行**溝通了。
在整個**的溝通過程中,**是我們和外界通訊的工具,對應到網路程式設計中socket就是我們和外界進行網路通訊的重要工具。
套接字位址格式
在使用套接字時首先要解決的是雙方的定址問題。
通用套接字位址格式
/* posix.1g 規範規定了位址族為2位元組的值. */
typedef
unsigned
short
int sa_family_t;
/* 描述通用套接字位址 */
struct sockaddr
;
在這個結構體裡第乙個欄位sa_family是位址族,它表示使用什麼樣的方式來對位址進行解釋和儲存,位址族在glibc中有很多的定義,常用的主要有如下的三種:
af_local:表示的是本地位址,對應的是unix套接字,這個一般用於本地通訊,也可以寫成是af_unix、af_file。
af_inet:網際網路使用的ipv4位址
af_inet6:網際網路使用的ipv6位址。
這裡的af表示的address family的意思,有時候也會有pf_***,pf表示的是protocol family協議族的意思。在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_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套接字位址,32bit值. */
typedef uint32_t in_addr_t;
struct in_addr ;
/* 描述ipv4的套接字位址格式 */
struct sockaddr_in
;
struct sockaddr_in的第乙個欄位也是sin_family位址族對應ipv4就是af_inet。然後是埠號,埠號為16位即最多就是65536個埠,而保留埠則是值大家眾所周知的已經被對應的服務光廣泛使用的埠,如ftp服務的21埠、ssh服務的22埠以及http服務的80埠等。glibc中定義的保留埠主要如下:
/* standard well-known ports. */
enum
ipv6套接字位址格式
ipv6的位址格式如下
struct sockaddr_in6
;
整個結構體的長度為28個位元組。其中sin6_addr公升級為128位,完全解決了定址位址不夠的問題。
本地套接字位址格式
struct sockaddr_un
;
本地套接字主要用於本地的程序間通訊,如前面提到的af_local.
幾種套接字位址格式的比較
幾種套接字的格式比較如下,其中ipv4和ipv6的套接字位址結構的長度是固定的,而本地套接字位址結構的長度是可變的。
Unix網路程式設計 1 套接字位址結構
ubuntu usr include netinet in.h includestruct in addr struct sockaddr in sin len 結構體長度字段。sin family 協議族字段。可取的值為 af unix 本地通訊 af inet ipv4 af int6 ipv6...
18 3 3 套接字位址
每個套接字域都有獨特的位址格式。對於乙個 af unix 套接字來說,它的位址是由乙個包含在 sys un.h 標頭檔案裡的 sockaddr un 結構描述的。該結構的定義為 struct sockaddr un 因為不同型別的位址都需要傳遞到對套接字程序處理的系統呼叫裡去,所以定義各種位址格式時...
網路程式設計7 套接字關閉
close 函式 int close int sockfd close函式會對套接字引用計數減一,一旦發現套接字引用計數到0,就會關閉tcp兩個方向的資料流,並徹底釋放套接字 在輸入方向上,系統核心會將套接字設定為不可讀,任何讀操作都會返回異常 在輸出方向上,系統核心嘗試將傳送緩衝區的資料傳送給對端...