網(wǎng)絡(luò)協(xié)議之:socket協(xié)議詳解之Unix domain Socket

簡介

之前的文章我們講到了Socket中的Stream Socket和Datagram Socket,這兩種Socket通常分別是基于tcp和udp協(xié)議來進(jìn)行數(shù)據(jù)的傳輸。這兩種Socket都有一個共同的特點,那就是需要一個IP地址和端口來建立客戶端和服務(wù)器端的連接。

那么今天我們會來講解一個特殊的socket,這個socket不需要使用傳統(tǒng)的IP地址和端口,而是使用文件系統(tǒng)來進(jìn)行程序之間的數(shù)據(jù)交互,并且這樣的socket只能使用在unix系統(tǒng)上。這樣的socket就是今天我們要講解的Unix domain Socket。

什么是Unix domain Socket

什么是Unix domain Socket呢? 我們從名字就可以看出來,這個Socket是和unix domain有關(guān)系的,也就是說這個socket需要用到unix下面的一些特殊功能。

我們考慮下常用的windows系統(tǒng)和unix系統(tǒng),他們最大的區(qū)別在哪里呢?

其實最大的區(qū)別就是unix操作系統(tǒng)中一切都可以看做是文件,包括程序運行的一些信息。

那么我們是不是可以直接借助于這些程序運行時產(chǎn)生的文件來進(jìn)行不同程序之間數(shù)據(jù)的交互呢?答案是肯定的。這就是我們今天要討論的Unix domain Socket。

Unix domain Socket可以簡稱為UDS,不同程序間的數(shù)據(jù)可以在操作系統(tǒng)層,借助于文件系統(tǒng)來進(jìn)行數(shù)據(jù)交換。

對于程序本身來說,只需要讀取和寫入共享的socket文件即可,也就是說不同的程序之間通過socket文件來進(jìn)行數(shù)據(jù)交互。

和基于IP和端口的Socket一樣,Unix domain Socket也可以分為Stream Socket和Datagram Socket。

我們最多看到Unix domain socket的地方可能就是docker了,作為一種容器技術(shù),docker需要和實體機(jī)進(jìn)行快速的數(shù)據(jù)傳輸和信息交換,一般情況下UDS的文件是以.socket結(jié)尾的,我們可以在/var/run目錄下面使用下面的命令來查找:

find . -name "*.sock"

如果你有docker在運行的話,可以得到下面的結(jié)果:

./docker.sock
./docker/libnetwork/6d66a24bfbbfa231a668da4f1ed543844a0514e4db3a1f7d8001a04a817b91fb.sock
./docker/libcontainerd/docker-containerd.sock

可以看到docker是通過上面的3個sock文件來進(jìn)行通訊的。

使用socat來創(chuàng)建Unix Domain Sockets

之前提到了socat這個萬能的工具,不僅可以創(chuàng)建tcp的監(jiān)聽服務(wù)器,還能創(chuàng)建udp的監(jiān)聽服務(wù)器,當(dāng)然對于UDS來說也不在話下。我們來看下使用socat來創(chuàng)建UDS服務(wù)器所需要用到的參數(shù):

      unix-listen:<filename>    groups=FD,SOCKET,NAMED,LISTEN,CHILD,RETRY,UNIX
      unix-recvfrom:<filename>  groups=FD,SOCKET,NAMED,CHILD,RETRY,UNIX

這里我們要使用到unix-listen和unix-recvfrom這兩個參數(shù),unix-listen表示的是創(chuàng)建stream-based UDS服務(wù),而unix-recvfrom表示的是創(chuàng)建datagram-based UDS。

可以看到兩個參數(shù)后面都需要傳入一個文件名,表示UDS socket的地址。

我們可以這樣使用:

socat unix-listen:/tmp/stream.sock,fork /dev/null&
socat unix-recvfrom:/tmp/datagram.sock,fork /dev/null&

這里我們使用/tmp/datagram.sock來表示這個socket信息。

其中fork參數(shù)表示程序在接收到程序包之后繼續(xù)運行,如果不用fork,那么程序會自動退出。

socat后面本來要接一個bi-address,這里我們使用/dev/null,表示丟棄掉所有的income信息。

運行后我們可能得到下面的結(jié)果:

[1] 27442
[2] 27450

表示程序已經(jīng)成功執(zhí)行了,返回的是程序的pid。

使用ss命令來查看Unix domain Socket

在使用ss命令之前,我們先來看下使用socat生成的兩個文件:

srwxrwxr-x   1 flydean flydean    0 Mar  2 21:58 stream.sock
srwxrwxr-x   1 flydean flydean    0 Mar  2 21:59 datagram.sock

可以看到這兩個文件的權(quán)限,rwx大家都懂,分別是read,write和執(zhí)行權(quán)限。那么最前面的s是什么呢?

最前面的一位表示的是文件類型,s表示的就是socket文件。

擴(kuò)展一下,這個位置還可以有其他幾種選項:p、d、l、s、c、b和-:

其中p表示命名管道文件,d表示目錄文件,l表示符號連接文件,-表示普通文件,s表示socket文件,c表示字符設(shè)備文件,b表示塊設(shè)備文件。

接下來我們使用ss命令來查看一下之前建立的UDS服務(wù)。

這里需要使用到下面幾個參數(shù):

   -n, --numeric       don't resolve service names
   -l, --listening     display listening sockets
   -x, --unix          display only Unix domain sockets

這里我們需要使用到上面3個選項,x表示的是顯示UDS,因為是監(jiān)聽,所以使用-l參數(shù),最后我們希望看到具體的數(shù)字,而不是被解析成了服務(wù)名,所以這里使用-n參數(shù)。

我們可以嘗試執(zhí)行一下下面的命令:

ss -xln

輸出會很多,我們可以grep我們需要的socket如下所示:

ss -xln | grep tmp
u_str  LISTEN     0      5      /tmp/stream.sock 11881005              * 0                  
u_dgr  UNCONN     0      0      /tmp/datagram.sock 11882190              * 0  

u_str表示的是UDS stream socket,而u_dg表示的是UDS datagram socket。

我們可以使用stat命令來查看socket文件的具體信息:

stat /tmp/stream.sock /tmp/datagram.sock
  File: ‘/tmp/stream.sock’
  Size: 0               Blocks: 0          IO Block: 4096   socket
Device: fd02h/64770d    Inode: 134386049   Links: 1
Access: (0775/srwxrwxr-x)  Uid: ( 1002/    flydean)   Gid: ( 1002/    flydean)
Access: 2022-03-01 22:33:21.533000000 +0800
Modify: 2022-03-01 22:33:21.533000000 +0800
Change: 2022-03-01 22:33:21.533000000 +0800
 Birth: -
  File: ‘/tmp/datagram.sock’
  Size: 0               Blocks: 0          IO Block: 4096   socket
Device: fd02h/64770d    Inode: 134386050   Links: 1
Access: (0775/srwxrwxr-x)  Uid: ( 1002/    flydean)   Gid: ( 1002/    flydean)
Access: 2022-03-01 22:33:22.306000000 +0800
Modify: 2022-03-01 22:33:22.306000000 +0800
Change: 2022-03-01 22:33:22.306000000 +0800
 Birth: -

使用nc連接到Unix domain Socket服務(wù)

nc是一個非常強(qiáng)大的工具,除了可以進(jìn)行TCP,UDP連接之外,還可以進(jìn)行UDS的連接,我們需要使用到下面的參數(shù):

  -U, --unixsock             Use Unix domain sockets only
  -u, --udp                  Use UDP instead of default TCP
  -z                         Zero-I/O mode, report connection status only

-U表示連接的是一個unixsocket。-u表示是一個UDP連接。

默認(rèn)情況下nc使用的是TCP連接,所以不需要額外的參數(shù)。

另外我們直接建立連接,并不發(fā)送任何數(shù)據(jù),所以這里使用-z參數(shù)。

先連接Stream UDS看看:

nc -U -z /tmp/stream.sock

如果沒有輸出任何異常數(shù)據(jù),說明連接成功了。

然后再連接Datagram UDS看看:

nc -uU -z /tmp/datagram.sock

同樣的,如果沒有任何異常數(shù)據(jù),說明Socket連接成功了。

總結(jié)

在本章我們詳細(xì)介紹了Unix Domain Socket的含義,并且使用了unix中的一些工具實現(xiàn)了UDS的建立,檢測和連接?;旧厦枋隽薝DS的使用情況。

本文已收錄于 http://www.flydean.com/17-unix-domain-socket/

最通俗的解讀,最深刻的干貨,最簡潔的教程,眾多你不知道的小技巧等你來發(fā)現(xiàn)!

歡迎關(guān)注我的公眾號:「程序那些事」,懂技術(shù),更懂你!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容