嵌牛導讀Linux進程間套接字通信基礎
嵌牛鼻子Linux 進程間套接字及通信介紹
嵌牛提問Linux進程間套接字包含哪些內容,如何實現通信
壹、套接字(Socket)通信原理
套接字通信允許互聯的位於不同計算機上的進程之間實現通信功能。
二、套接字的屬性
套接字的特性由3個屬性確定,它們分別是:域、類型和協議。
1. 套接字的域
它指定套接字通信中使用的網絡介質,最常見的套接字域是AF_INET,它指的是Internet網絡。當客戶使用套接字進行跨網絡的連接時,它就需要用到服務器計算機的IP地址和端口來指定壹臺聯網機器上的某個特定服務,所以在使用socket作為通信的終點,服務器應用程序必須在開始通信之前綁定壹個端口,服務器在指定的端口等待客戶的連接。
另壹個域AF_UNIX表示UNIX文件系統,就是文件輸入/輸出,它的地址就是文件名。
2. 套接字類型
因特網提供了兩種通信機制:流(stream)和數據報(datagram),因而套接字的類型也就分為流套接字和數據報套接字。我們主要看流套接字。
流套接字由類型SOCK_STREAM指定,它們是在AF_INET域中通過TCP/IP連接實現,同時也是AF_UNIX中常用的套接字類型。
流套接字提供的是壹個有序、可靠、雙向字節流的連接,因此發送的數據可以確保不會丟失、重復或亂序到達,而且它還有壹定的出錯後重新發送的機制。
與流套接字相對的是由類型SOCK_DGRAM指定的數據報套接字,它不需要建立連接和維持壹個連接,它們在AF_INET中通常是通過UDP/IP實現的。它對可以發送的數據的長度有限制,數據報作為壹個單獨的網絡消息被傳輸,它可能丟失、復制或錯亂到達,UDP不是壹個可靠的協議,但是它的速度比較高,因為它並不需要總是要建立和維持壹個連接。
3.套接字協議
只要底層的傳輸機制允許不止壹個協議來提供要求的套接字類型,我們就可以為套接字選擇壹個特定的協議。通常只需要使用默認值。
三、套接字地址
每個套接字都有其自己的地址格式,對於AF_UNIX域套接字來說,它的地址由結構sockaddr_un來描述,該結構定義在頭文件
struct sockaddr_un{
sa_family_t sun_family;? //AF_UNIX,它是壹個短整型
char sum_path[];? //路徑名
};
對於AF_INET域套接字來說,它的地址結構由sockaddr_in來描述,它至少包括以下幾個成員:
struct sockaddr_in{
short int sin_family;? //AN_INET
unsigned short int sin_port;? //端口號
struct in_addr sin_addr; //IP地址
}
而in_addr被定義為:
struct in_addr{
unsigned long int s_addr;
}
四、基於流套接字的客戶/服務器的工作流程
使用socket進行進程通信的進程采用的客戶/服務器系統是如何工作的呢?
1.服務器端
首先,服務器應用程序用系統調用socket來創建壹個套接字,它是系統分配給該服務器進程的類似文件描述符的資源,它不能與其他的進程***享。
接下來,服務器進程會給套接字起個名字,我們使用系統調用bind來給套接字命名。然後服務器進程就開始等待客戶連接到這個套接字。
然後,系統調用listen來創建壹個隊列,並將其用於存放來自客戶的進入連接。
最後,服務器通過系統調用accept來接受客戶的連接。它會創建壹個與原有的命名套接不同的新套接字,這個套接字只用於與這個特定客戶端進行通信,而命名套接字(即原先的套接字)則被保留下來繼續處理來自其他客戶的連接。
2.客戶端
基於socket的客戶端比服務器端簡單。同樣,客戶應用程序首先調用socket來創建壹個未命名的套接字,然後講服務器的命名套接字作為壹個地址來調用connect與服務器建立連接。
壹旦連接建立,我們就可以像使用底層的文件描述符那樣用套接字來實現雙向數據的通信。