在linux中,套接字文件是一種特殊的文件類型,用于通信,它提供了受文件系統訪問控制保護的進程間通信。套接字就是支持TCP/IP網絡通信的基本操作單元,linux以文件的形式實現套接口,與套接口相應的文件屬于sockfs特殊文件系統,創建一個套接口就是在sockfs中創建一個特殊文件,并建立起為實現套接口功能的相關數據結構。
本教程操作環境:linux7.3系統、Dell G3電腦。
套接字文件是什么
套接字文件是一種特殊的文件類型,它用于進程間通信。套接字文件可以被讀取、寫入和執行。在Linux系統中,套接字文件通常用于網絡編程。
使用ls -l 命令查看,第一個字符為 “s”(socket)。
套接字是一種特殊的文件類型,類似于TCP / IP套接字,它提供了受文件系統訪問控制保護的進程間通信。
例如,當您使用netcat在一個終端中打開監聽套接字時:
nc?-lU?socket.sock
然后通過以下方式從另一個終端發送數據:
echo?mytext?|?nc?-U?socket.sock
mytext出現在第一個終端上。
默認情況下,nc在文件結束字符后停止監聽。
套接字Socket
為了區別不同的應用程序進程和連接,許多計算機操作系統為應用程序與TCP/IP協議交互提供了稱為套接字(Socket)的接口。
套接口可以說是網絡編程中一個非常重要的概念,linux以文件的形式實現套接口,與套接口相應的文件屬于sockfs特殊文件系統,創建一個套接口就是在sockfs中創建一個特殊文件,并建立起為實現套接口功能的相關數據結構。換句話說,對每一個新創建的BSD套接口,linux內核都將在sockfs特殊文件系統中創建一個新的inode。
套接字簡介
套接字就是支持TCP/IP網絡通信的基本操作單元,是我們進行TCP/IP進行通信的接口。
linux以文件的形式實現套接口,與套接口相應的文件屬于sockfs特殊文件系統,創建一個套接口就是在sockfs中創建一個特殊文件,并建立起為實現套接口功能的相關數據結構。換句話說,對每一個新創建的套接字,linux內核都將在sockfs特殊文件系統中創建一個新的inode。
套接字Socket看做是不同主機之間的進程進行雙向通信的端點,簡單的說就是通信的兩方的一種約定,用套接字中的相關函數來完成通信過程。套接字Socket是連接應用程序和網絡驅動程序的橋梁,套接字Socket在應用程序中創建,通過綁定與網絡驅動建立關系。此后,應用程序送給套接字Socket的數據,由套接字Socket交給網絡驅動程序向網絡上發送出去。計算機從網絡上收到與該套接字Socket綁定IP地址和端口號相關的數據后,由網絡驅動程序交給Socket,應用程序便可從該Socket中提取接收到的數據,網絡應用程序就是這樣通過Socket進行數據的發送與接收的。
操作系統區分不同應用程序進程間的網絡通信和連接,主要有3個參數:通信的目的IP地址、使用的傳輸層協議(TCP或udp)和使用的端口號。
套接字連接的過程如同(客戶)打一個電話到一個大公司,接線員(服務器進程)接聽電話并把它轉接到你要找的部門,然后再從那里轉到你要找的人(服務器套接字),然后接線員(服務器進程)再繼續轉接其它(客戶)的電話。
套接字有本地套接字和網絡套接字兩種。本地套接字的名字是Linux文件系統中的文件名,一般放在/tmp或/usr/tmp目錄中;網絡套接字的名字是與客戶連接的特定網絡有關的服務標識符(端口號或訪問點)。這個標識符允許Linux將進入的針對特定端口號的連接轉到正確的服務器進程。
套接字類型
常用的TCP/IP協議的3種套接字類型如下所示。
流套接字(SOCK_STREAM):
流套接字用于提供面向連接、可靠的數據傳輸服務。看到這個我們想到了什么,是不是TCP
該服務將保證數據能夠實現無差錯、無重復發送,并按順序接收。流套接字之所以能夠實現可靠的數據服務,原因在于其使用了傳輸控制協議,即TCP(The Transmission Control Protocol)協議。
數據報套接字(SOCK_DGRAM)
數據報套接字提供了一種無連接的服務。該服務并不能保證數據傳輸的可靠性,數據有可能在傳輸過程中丟失或出現數據重復,且無法保證順序地接收到數據。數據報套接字使用UDP(User Datagram Protocol)協議進行數據的傳輸。由于數據報套接字不能保證數據傳輸的可靠性,對于有可能出現的數據丟失情況,需要在程序中做相應的處理。
原始套接字(SOCK_RAW)
原始套接字(SOCKET_RAW)允許對較低層次的協議直接訪問,比如IP、 ICMP協議,它常用于檢驗新的協議實現,或者訪問現有服務中配置的新設備,因為RAW SOCKET可以自如地控制windows下的多種協議,能夠對網絡底層的傳輸機制進行控制,所以可以應用原始套接字來操縱網絡層和傳輸層應用。比如,我們可以通過RAW SOCKET來接收發向本機的ICMP、IGMP協議包,或者接收TCP/IP棧不能夠處理的IP包,也可以用來發送一些自定包頭或自定協議的IP包。網絡監聽技術很大程度上依賴于SOCKET_RAW
原始套接字與標準套接字(標準套接字指的是前面介紹的流套接字和數據報套接字)的區別在于:原始套接字可以讀寫內核沒有處理的IP數據包,而流套接字只能讀取TCP協議的數據,數據報套接字只能讀取UDP協議的數據。因此,如果要訪問其他協議發送數據必須使用原始套接字。
重要數據結構
下面是在網絡編程中比較重要的幾個數據結構
表示套接口的數據結構Struct socket
用戶使用socket系統調用編寫應用程序時,通過一個數字來表示一個socket,所有的操作都在該數字上進行,這個數字稱為套接字描述符。在系統調用 的實現函數里,這個數字就會被映射成一個表示socket的結構體,該結構體保存了該socket的所有屬性和數據。
套接口是由socket數據結構代表的,形式如下
struct?socket { socket_state?state;?/*指明套接口的連接狀態,一個套接口的連接狀態可以有以下幾種 套接口是空閑的,還沒有進行相應的端口及地址的綁定;還沒有連接;正在連接中;已經連接;正在解除連接。*/unsignedlong?flags; structproto_ops?ops;?/*指明可對套接口進行的各種操作*/structinode?inode;?/*指向sockfs文件系統中的相應inode*/structfasync_struct?*fasync_list;?/*?Asynchronous?wake?up?list?*/structfile?*file;?/*指向sockfs文件系統中的相應文件?*/structsock?sk;?/*任何協議族都有其特定的套接口特性,該域就指向特定協議族的套接口對 象。*/wait_queue_head_t?wait; short?type;unsignedchar?passcred; };
描述套接口通用地址的數據結構struct sockaddr
由于歷史的緣故,在bind、connect等系統調用中,特定于協議的套接口地址結構指針都要強制轉換成該通用的套接口地址結構指針。結構形式如下:
struct?sockaddr?{ sa_family_t?sa_family;?/*?address?family,?AF_xxx,?sa_family是地址家族,一般都是“AF_xxx”的形式。通常大多用的是都是AF_INET,代表TCP/IP協議族。*/ char?sa_data[14];??????/*14?bytes?of?protocol?address,?sa_data是14字節協議地址。*/ };
此數據結構用做bind、connect、recvfrom、sendto等函數的參數,指明地址信息。但一般編程中并不直接針對此數據結構操作,而是使用另一個與sockaddr等價的數據結構
描述因特網地址結構的數據結構struct sockaddr_in
每個套接字域都有自己的地址格式。?
AF_UNIX 域套接字格式:
#include?<sys> #define?UNIX_PATH_MAX ????108struct?sockaddr_un?{? ????sa_family_t?sun_family;???????????????/ ????*?AF_UNIX?*/? ????char????????sun_path[UNIX_PATH_MAX];??/*?pathname?*/? ????};</sys>
AF_INET 域套接字格式IPV4:
/*?Internet?address.?*/ struct?in_addr?{ ????uint32_t??????? ????s_addr;?????/*?address?in?network?byte?order?*/ ????};
IP地址是由4個字節組成的一個32位的值。
#include?<netinet> struct?sockaddr_in {????short?sin_family;/*??Addressfamily一般來說AF_INET(地址族)PF_INET(協議族)??*/ ????unsigned?short?sin_port;/*?Portnumber(必須要采用網絡數據格式,普通數字可以用htons()函數轉換成網絡數據格式的數字)?*/ ????struct?in_addr?sin_addr;/*?Internetaddress存儲IP地址??*/ ????unsigned?char?sin_zero[sizeof(struct?sockaddr)?-?__SOCKADDR_COMMON_SIZE?-?sizeof(in_port_t)?-?sizeof(struct?in_addr)];??/*?Samesizeasstructsockaddr沒有實際意義,只是為了 跟SOCKADDR結構在內存中對齊*/ };</netinet>
AF_INET6 域套接字格式IPV6:
struct?sockaddr_in6?{? ????sa_family_t?????sin6_family;???/*?AF_INET6?*/? ????in_port_t???????sin6_port;?????/*?port?number?*/? ????uint32_t????????sin6_flowinfo;?/*?IPv6?flow?information?*/? ????struct?in6_addr?sin6_addr;?????/*?IPv6?address?*/? ????uint32_t????????sin6_scope_id;?/*?Scope?ID?(new?in?2.4)?*/? }; struct?in6_addr?{? ????unsigned?char???s6_addr[16];???/*?IPv6?address?*/? };
對于應用程序來說,套接字就和文件描述符一樣,并且通過一個唯一的整數值來區分。
相關推薦:《Linux視頻教程》